Shell编程(/bin/sh和/bin/bash)
查看ubuntu支持的Shell:
$ cat /etc/shells
查看当前shell:
$ echo $SHELL
以下是sh Shell脚本编程,也适用于bash,差异之处已说明。
保留字符及其含义
$ shell变量名的开始,如$var
| 管道,将标准输出转到下一个命令的标准输入
# 注释开始
& 在后台执行一个进程
? 匹配一个字符
* 匹配0到多个字符(与DOS不同,可在文件名中间使用,并且含.)
$- 使用set及执行时传递给shell的标志位
$! 最后一个子进程的进程号
$# 传递给shell script的参数个数
$* 传递给shell script的参数
$@ 所有参数,个别的用双引号括起来
$? 上一个命令的返回代码
$0 当前shell的名字
$n (n:1-) 位置参数
$$ 进程标识号(Process Identifier Number, PID)
>file 输出重定向
`command` 命令替换,如 filename=`basename /usr/local/bin/tcsh`
>>fiile 输出重定向,append
其他:
$$dir
ls > filelist
ls >> filelist
wc -l < filelist
wc -l filelist
sleep 5; echo 5 seconds reaches; ls -l
ps ax |egrep inetd
find / -name core -exec rm {} \; &
filename=`date "+%Y%m%d"`.log
shell变量
Shell有如下四种变量:
.用户自定义变量
.位置变量即 shell script之参数
.预定义变量(特殊变量)
.环境变量
(1)用户自定义变量(数据的存储)
$ COUNT=1
$ NAME="He Binwu"$ echo $NAME$ echo ${NAME}
技巧:因为大部分UNIX命令使用小写字符,因此在shell编程中通常使用全大写变量,当然这并不是强制性的,但使用大写字符可以在编程中方便地识别变量。
变量的调用:在变量前加$。
使用unset命令删除变量的赋值。
$ Z=hello
$ echo
$Zhello
$ unset Z
$ echo $Z
$
在变量未赋值之前其值为空。Bourne Shell允许对变量设置默认值(相当于C#中 ?? 表达式),其格式如下:
${variable:-defaultvalue}
例:
$ echo Hello $UNAME
Hello
$ echo Hello ${UNAME:-there}
Hello there
$ echo $UNAME #变量值并未发生变化
there
$ UNAME=hbwork
$ echo Hello ${UNAME:-there}
Hello hbwork
另一种情况:改变变量的值,格式如下:
${variable:=value}
$ echo Hello $UNAME
Hello
$ echo Hello ${UNAME:=there}
Hello there
$ echo $UNAME #变量值并未发生变化
there
变量替换中使用命令替换:
echo ${MYDIR} #输出空
echo ${MYDIR:-`pwd`}输出:
/home/pxl/shelltest
在变量已赋值时进行替换:
MYTEST=pxl
echo ${MYTEST}
echo ${MYTEST:+"changevalue"}
echo $MYTEST
输出:
pxl
changevalue
pxl
带有错误检查的有条件变量替换:
echo ${UNAME:?"UNAME has not been set"}
echo ${UNAME} #如果上一句判断错误,这里不会执行输出:./test.sh: 17: UNAME: UNAME has not been set
(2)位置变量(Shell参数)
在shell script中位置参数可用$1..$9表示,$0表示内容通常为当前执行程序的文件名。
可以使用shift [n] 来删出指定前n个参数,n默认为1.
脚本test.sh:shift
shift 2
echo $1echo $0
执行:
$ ./test.sh a b c d e
输出:
d./test.sh
条件测试命令
(1)数值测试:
-eq :等于则为真。
-ne :不等于则为真。
-gt :大于则为真。
-ge :大于等于则为真。
-lt :小于则为真。
-le :小于等于则为真。
(2)字串测试:
= :等于则为真。
!= :不相等则为真。
-z字串 :字串长度伪则为真。
-n字串 :字串长度不伪则为真。
(3)文件测试:
-e文件名 :如果文件存在则为真。
-r文件名 :如果文件存在且用户有读权限则为真。
-w文件名 :如果文件存在且用户有写权限则为真。
-x文件名 :如果文件存在且用户有可执权限行则为真。
-s文件名 :如果文件存在且至少有一个字符(大小不为零)则为真。
-d文件名 :如果文件存在且为目录则为真。
-f文件名 :如果文件存在且为普通文件则为真。
-c文件名 :如果文件存在且为字符设备文件则为真。
-b文件名 :如果文件存在且为块设备文件则为真。
表达式
(1) 与、或、非
&& :与
|| :或
! : 非(需要有空格)
(2) expr命令
expr命令一般用于整数值,但也可用于字符串。一般格式为:
expr argument operator argument
其中operator为+ - * / %, 但对*的使用要用转义符\。
v1=3
v2=2
v3=`expr $v1 \* $v2`
echo $v3输出:6
#适用于/bin/bash,不适用于/bin/sh
v1=3
v2=2
v3=$[v1*v2]
echo $v3
流程控制
(1) if 条件语句
if [ -f "$file" ] ; then
newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
if [ -f "$newfile" ]; then
echo "ERROR: $newfile exists already"
else
echo "renaming $file to $newfile ..."
mv "$file" "$newfile"
fi
fi
(2) for 循环
for file in $*; do
if [ -f "$file" ] ; then
newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
if [ -f "$newfile" ]; then
echo "ERROR: $newfile exists already"
else
echo "renaming $file to $newfile ..."
mv "$file" "$newfile"
fi
fi
done
for n in 9 8 7 6 5 4 3 2 1; do
if [ -f "$filen.$n" ]; then
p=`expr $n + 1`
echo "mv $filen.$n $filen.$p"
mv $filen.$n $filen.$p
fi
done
#适用于/bin/bash,不适用于sh
for((i=1;i<=10;i++));do
echo $i
done
(3) while 循环
while [ -n "$1" ]; do
echo $1
shift
done
(4) case 条件
while [ -n "$1" ]; do
case $1 in
-h) help;shift 1;; # function help is called
-f) opt_f=1;shift 1;; # variable opt_f is set
-l) opt_l=$2;shift 2;; # -l takes an argument -> shift by 2
--) shift;break;; # end of options
-*) echo "error: no such option $1. -h for help";exit 1;;
*) break;;
esac
done
参考资料