首页 | 新闻 | 交流 | 问吧 | 文档 | 手册 | 下载 | 博客

Shell编程(/bin/sh和/bin/bash)

作者:  时间: 2010-11-30

查看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 $
1
echo $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

 

参考资料

Shell编程基础

shell编程简介