接第三部分。
第四章 Linux shell程序设计
4.1 shell概述
shell的特点和主要版本
linux默认使用的是bash,具有很好的兼容性,提高了效率,有如下特点:
- 对已有命令进行组合,比如通过管道、重定向等
- 通过tab 可以进行自动补全
- 可以使用通配符如 *,?,[]
- 提供后台运行的能力
- 有结构化的程序模块
linux 支持的shell 有下面版本:
- bash
- c shell
- k shell
- zsh
我们学习linux以bash为主,它也是linux 默认的shell版本
exam1是一个简单的脚本文件:顺序执行,如果在一行可以用分好分开
[root@heqiuyu gl]# vim exam1.sh
[root@heqiuyu gl]# sh exam1.sh
2018年 04月 30日 星期一 19:46:20 PDT
/root/gl
[root@heqiuyu gl]# cat exam1.sh
date
pwd
cd /
exam2是一个循环的文件:
[root@heqiuyu gl]# sh exam2.sh
exam1.sh exam2.sh uid.sh
[root@heqiuyu gl]# mkdir 1
[root@heqiuyu gl]# mkdir 2
[root@heqiuyu gl]# sh exam2.sh 1 2
1 2 exam1.sh exam2.sh uid.sh
[root@heqiuyu gl]# cat exam2.sh
#!/bin/bash
if test $#=0
then
ls
else
for i
do
ls -l $i | grep '^d'
done
fi
shell 脚本的建立与执行
步骤:
- 通过vim 建立shell脚本文件,建议后缀为.sh
- 文件第一行内容为 #!/bin/bash
- sh 文件名 执行 或者 chmod a+x 文件名 ,./文件名执行
4.2 历史命令
显示历史命令
history
该命令是用来显示用户的历史命令,这是我们接触到的第34个命令,参数 -c 清楚历史命令
[root@heqiuyu gl]# history
84 ls
85 rm -rf 11*
86 ls
87 rm -rf 22
88 rm -rf aaaa
89 rm -rf ccc*
90 ls
91 rm ceshi* -rm
92 rm ceshi* -rf
93 rm kkk -r
通过! n 可以执行第n 条历史命令
[root@heqiuyu gl]# !86
ls
1 2 exam1.sh exam2.sh uid.sh
[root@heqiuyu gl]# ls
1 2 exam1.sh exam2.sh uid.sh
[root@heqiuyu gl]# env | grep HIS //代表显示多少条历史命令
HISTSIZE=1000
通过tab 进行自动补全
4.4 别名
alias
用来显示和设置别名,不加任何参数,输出已经有的别名,这是我们接触到的第35个命令
[root@heqiuyu gl]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
设置别名,比如我要通过cip 修改网卡文件 vim /etc/sysconfig/network-scripts/ifcfg-eth0
[root@heqiuyu gl]# alias
alias cip='vim /etc/sysconfig/network-scripts/ifcfg-eth0 '
alias cp='cp -i'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
取消别名,这是我们接触到的第36个命令
unalias
4.5 shell 特殊字符
一般通配符
- *匹配任意字符的0次或者多次
- ?匹配任意一个字符
- [] 匹配该字符组所限定的任何一个字符
- !和[] 配合使用,[!1-9] 不包含数字
[root@heqiuyu gl]# ls ex*
exam1.sh exam2.sh
双引号
变量解析后输出
[root@heqiuyu gl]# name=heqiuyu
[root@heqiuyu gl]# echo "$name is test"
heqiuyu is test
单引号
原样输出
[root@heqiuyu gl]# echo '$name is test'
$name is test
倒引号
字符被shell 先解释
[root@heqiuyu gl]# today=`date`
[root@heqiuyu gl]# echo $today
2018年 04月 30日 星期一 20:12:30 PDT
> 重定向输出
[root@heqiuyu gl]# cat /etc/passwd > ./pass
[root@heqiuyu gl]# cat pass | head -5
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
>> 重定向追加
[root@heqiuyu gl]# cat pass | tail -3 >> ./pass
[root@heqiuyu gl]# cat pass
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
系统为每个进程自动打开三个标准文件(即标准输入,标准输出,错误输出),其文件描述符分别为 0 1 2
[root@heqiuyu gl]# asdfdsf 2>ccc
[root@heqiuyu gl]# cat ccc
-bash: asdfdsf: command not found //错误重定向
[root@heqiuyu gl]# uname >ddd
[root@heqiuyu gl]# cat ddd //标准输出
Linux
2>&1 正确和错误都输出
命令执行操作符
- ; 一行两条命令
- && 逻辑与
- || 逻辑或
数组
bash只提供一维数组,下标从0开始
[root@heqiuyu gl]# city[0]=beijing
[root@heqiuyu gl]# city[2]=shanghai
[root@heqiuyu gl]# city[3]=huanghua
[root@heqiuyu gl]# echo ${city[*]}
beijing shanghai huanghua
也可以用declare -a 数组名 定义一个数组
[root@heqiuyu gl]# declare -a arr
[root@heqiuyu gl]# arr=(this is a arr)
[root@heqiuyu gl]# echo ${arr[@]}
this is a arr
read
读取变量,这是我们接触到的第37个命令
-p 代表提示符,-t 等待时间
[root@heqiuyu gl]# read -p "please input your name " name
please input your name heqiuyu
[root@heqiuyu gl]# echo $name
heqiuyu
shell 脚本的位置参数
- $0 脚本名称
- $1 第一个参数
- $* 所有参数
- $# 参数个数
- $? 脚本执行的返回值
- ? 进程号
- $!上一个后台对于的进程号
[root@heqiuyu gl]# vim hello.sh
[root@heqiuyu gl]# cat hello.sh
echo "The name of file is $0"
echo "The total number is $#"
echo "The process is ?"
echo "The return code is $?"
[root@heqiuyu gl]# chmod a+x hello.sh
[root@heqiuyu gl]# ./hello.sh
The name of file is ./hello.sh
The total number is 0
The process is 33707
The return code is 0
[root@heqiuyu gl]# ./hello.sh 1 2 3
The name of file is ./hello.sh
The total number is 3
The process is 33729
The return code is 0
环境变量
环境变量可以在Linux中使用,一般有大写字母构成,env 命令输出已经定义的环境变量,这是我们接触到的第37个命令
[root@heqiuyu ~]# env
LC_PAPER=zh_CN.UTF-8
LC_ADDRESS=zh_CN.UTF-8
HOSTNAME=heqiuyu
LC_MONETARY=zh_CN.UTF-8
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=10.10.9.190 38178 22
SELINUX_USE_CURRENT_RANGE=
LC_NUMERIC=zh_CN.UTF-8
QTDIR=/usr/lib64/qt-3.3
QTINC=/usr/lib64/qt-3.3/include
SSH_TTY=/dev/pts/2
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
LC_TELEPHONE=zh_CN.UTF-8
MAIL=/var/spool/mail/root
PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
LC_IDENTIFICATION=zh_CN.UTF-8
PWD=/root
LANG=en_US.UTF-8
LC_MEASUREMENT=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
QTLIB=/usr/lib64/qt-3.3/lib
CVS_RSH=ssh
SSH_CONNECTION=10.10.9.190 38178 10.10.8.119 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
LC_TIME=zh_CN.UTF-8
G_BROKEN_FILENAMES=1
LC_NAME=zh_CN.UTF-8
_=/bin/env
OLDPWD=/root/gl
- HOME :代表使用者的家目录。cd ~ 去到使用者的家目录或者利用cd 就可以直接回到使用者家目录了。
- PS1:shell的主提示符
- SHELL :目前这个环境使用的SHELL 是哪个程序?如果是bash 的话,预设是/bin/bash
- PWD:用户当前工作目录的路径。它指出用户目前在Linux文件系统中处在什么位置。它是由Linux自动设置的
- HISTSIZE :这个与“历史命令”有关,曾经下达过的指令可以被系统记录下来,而记录的“数目”则是由这个值来设定的。
-ENV :这个使用者所使用的个性化环境设置文件的读取文件。
MAIL :当我们使用mail 这个指令在收信时,系统会去读取的邮件信箱文件(mailbox)。
- PATH :就是执行文件搜寻的路径,目录与目录中间以冒号(:)分隔,由于文件的搜寻是依序由PATH 的变量内的目录来查询,所以,目录的顺序也是重要的喔。
- LANG :语系文件,很多数据都会用到他,当出现编码错误的时候往往需要设置它,中文编码是zh_CN.UTF8
环境变量的文件
- /etc/profile 存放一些全局(共有)变量,不管哪个用户,登录时都会读取该文件。通常设置一些Shell变量PATH,USER,HOSTNAME和HISTSIZE等
- ~/.bash_profile:每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件.
- ~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该该文件被读取.
- /etc/bashrc:为每一个运行bash shell的用户执行此文件.当bash shell被打开时,该文件被读取.
export
用于声明环境变量
set
显示迄今为止所有的变量
4.7参数置换变量
格式 =${变量 1 op 字符串},op是操作符,:-, :=, :+,:?
4.8 算术运算
let 这是我们接触的第39个命令,等于(( ))
[root@heqiuyu ~]# echo $((2*8))
16
[root@heqiuyu ~]# let 2*8
[root@heqiuyu ~]# let v=2*8
[root@heqiuyu ~]# echo $v
16
4.9 控制结构
if 语句
关键字有if,fi,then,else
格式:
- if 测试条件
- then 命令1
- else 命令2
- fi
[root@heqiuyu gl]# sh if.sh
“输入了0个参数”
[root@heqiuyu gl]# cat if.sh
#!/bin/bash
if [ $# -eq 0 ]
then
echo “输入了0个参数”
elif [ $# -lt 1 ]
then echo “输入了多个参数”
else echo “输入了1个参数”
fi
case 语句
也是判断选择语句
[root@heqiuyu gl]# sh case.sh
“输入了多个参数”
[root@heqiuyu gl]# sh case.sh 1
“输入了多个参数”
[root@heqiuyu gl]# cat case.sh
#!/bin/bash
case “$#” in
0)echo “输入了0个参数”;;
1)echo “输入了1个参数”;;
*)echo “输入了多个参数”;;
esac
for 循环
结构 for do done
[root@heqiuyu gl]# sh for.sh
1
2
3
4
^C
[root@heqiuyu gl]# cat for.sh
#!/bin/bash
for i in `seq 100`
do
echo $i
sleep 1
done
[root@heqiuyu gl]#
条件测试
格式 test 或者 []
文件测试:
- -f存在且是普通文件
- -d存在且是目录
- -s存在且字节数大于0
- -r存在且可读
- -w存在且可写
- -x存在且可执行
- 如:test -d “mydoc”
判断mydoc是否是目录
while
格式:
while
do
done
例子:
[root@heqiuyu gl]# sh while.sh
5050
[root@heqiuyu gl]# cat while.sh
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
sum=$[$sum+$i]
i=$[$i+1]
done
echo $sum
4.10 函数
[root@heqiuyu gl]# sh f.sh
programme starts here...
Enter Your name:
heqiuyu
Hello heqiuyu
programme ends.
[root@heqiuyu gl]# cat f.sh
#!/bin/bash
function sayhello ( )
{
echo "Enter Your name:"
read name
echo "Hello $name"
}
echo "programme starts here..."
sayhello
echo "programme ends."
[root@heqiuyu gl]#
4.11 作业控制
有关作业管理的命令:
jobs,kill,bg,fg
停止程序:
[root@heqiuyu ~]# ps -aux | grep seq
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
root 47816 77.9 0.0 100940 700 pts/2 R 01:42 0:17 seq 1000000000000000000
root 47839 0.0 0.0 103328 888 pts/0 S+ 01:42 0:00 grep seq
You have new mail in /var/spool/mail/root
[root@heqiuyu ~]# kill 47816
[root@heqiuyu ~]#
4.12 C 程序
gcc 编译,默认生成a.out
生成指定的目标文件 -o