Shell中有三种类型的循环:for, until, while,具有3种类型的条件语句:if, case, 条件操作符(&&, ||)。
1. 结束码
命令的结束码可以在命令运行完后,查看$?查看。当命令执行正常时,结束码为0,当异常时,返回1-255的数字。
$ printf "%v " -bash: printf: `v': invalid format character $ echo $? 1 $ mkdir /qwerty mkdir: cannot create directory `/qwerty': Permission denied $ echo $? 1
2. test命令
test命令用于计算多种表达式,包括文件属性,整型,字符串等。与test对应的,常见有两种符号:[[和((。其中((用于测试数值表达式,[[ ... ]]用于测试正则表达式。具体可以查看man test。
注意:[ test和[test是2个概念,bash对于空格比较敏感。
(1) 文件测试
a. -e: 表示文件是否存在
b. -f: 检查文件是否存在并且是否为普通文件
c. -d: 检查是否为文件夹
-h, -L: 是否为符号链接
$ test -f /etc/fstab # 当为普通文件时为true $ echo $? 0 $ test -h /etc/rc.local # 当为软连接时为true $ [ -x "$HOME/bin/hw" ] # 当指定文件可执行时为true $ [[ -s $HOME/bin/hw ]] # 当文件存在且非空时为true
(2) 整型测试
整型比较常见符号有-eq, -ne, -gt, -lt, -le
$ test 1 -eq 1 # 测试是否相等 $ echo $? 0 $ [ 2 -eq 1 ] $ echo $? 1 $ [ 2 -ne 1 ] # 测试不等 $ echo $? 0
(3) 字符串测试
a. =:字符串相等,等同于" == ",例:test "$a" = "$b"
b. != : 字符串不相等,例:[ "$q" != "$b" ]
c. -z : 字符串是否为空,例:[ -z "" ]
d. -n : 字符串是否非空,例:test -n ""
e. 字符串比较大小,注意 >, <防止被解释为重定向。例:
$ str1=abc $ str2=def $ test "$str1" < "$str2" $ echo $? 0 $ test "$str1" > "$str2" $ echo $? 1
f. -a : 逻辑与,等同于" && ",例:test -f /path/to/file -a $test -eq 1
g. -o : 逻辑或,等同于" || ",例:test -x bin/file -o $test -gt 1
3. [[ ... ]] : 计算一个表达式
如:[[ -f music_job.zip && 1 -eq 1 ]]
[[ ... ]]有个特征,即通过使用=~操作符来匹配正则表达式。
$ [[ $string =~ h[aeiou] ]] $ echo $? 0 $ [[ $string =~ h[sdfghjkl] ]] $ echo $? 1
4. (( ... )):计算算术表达式
(( 算数表达式 )),当其中的算术表达式计算为0时,返回false,否则为true。例:
$ test $(( a - 2 )) -ne 0 $ [ $a != 0 ]
由于(( ... ))是shell语法而非内置命令,因此 >, <符号将不会被当做重定向符。
例a:if (( total > max )); then: ...; fi
例b: (( verbose )) && command ## 当verbose != 0时,执行command命令
在(( ... ))中如果存在非数值,则默认结果为0,例:
$ y=yes $ ((y)) && echo $y || echo n n
注意:当(( ... ))中的变量代表数字时,可省略$符号
5. 条件执行
(1) if
格式为:
if <condition list> then <list> fi
示例:
example 1: read name if [[ -z $name ]];then echo "No name enterd" >&2 exit 1 fi example 2: printf "Enter a number not greater than 10: " read number if (( number > 10 ));then printf "%d is too big " "$number" >&2 exit 1 else printf "You entered %d " "$number" fi example 3: printf "Enter a number between 10 and 20 inclusive: " read number if (( number < 10 )); then printf "%d is too low " "$number" >&2 exit 1 elif (( number > 20 ));then printf "%d is too high " "$number| >&2 exit 1 else printf "You entered %d " "$number" fi
(2) 条件操作符&&, ||
包含&&, ||条件运算符的列表将从左向右依次执行。只有&&前的命令执行成功,才会执行&&后的命令;只有||前的命令执行失败,才会执行||后的命令。
例a:test -d "$director" && cd "$director" ## 检测目录存在,才会进入
例b: cd "$HOME/bin" || exit 1 ## 进入bin目录失败时,将会退出
例c: mkdir "$HOME/bin" && cd "$HOME/bin" || exit 1 ## 创建bin目录失败或进入bin目录失败,将退出
例:
if [ -d "$dir" ] && cd "$dir";then echo "$PWD" fi
(3) case
格式为:
case WORD in PATTERN) COMMANDS ;; PATTERN) COMMANDS ;; esac
例:case用于检测字符串是否包含:
case $1 in *"$2"*) echo "true" ;; *) echo "false" ;; esac
例:case用于判断数值是否有效
case $1 in *[!0-9]*) false ;; *) true ;; esac
例:判断参数的个数
case $# in 3) ;; ## We need 3 args, so do nothing *) printf "%s " "Please provide three names" >&2 exit 1 ;; esac
6. 循环
(1) while
格式为:
while <list> do <list> done
例:累加
n=1 while [ $n -le 10] do n=$(( $n + 1 )) done
例:true条件则无限循环
while true do read x done
例:从文件中逐行读取
while IFS= read -r line do : do something with "$line" done < FILENAME?
(2) until
until与while相反,当循环条件失败时结束。例:
n=1 until [ $n -gt 10 ] do echo "$n" n=$(( $n + 1 )) done
(3) for
for var in Canada USA Mexico do printf "%s " "$var" done
另一种格式:
for (( n=1; n<=10; ++n)) do echo "$n" done
(4) break
while : do read x [ -z "$x" ] && break #输入为空字符串时,退出 done
break后如果带有数值,则表示可以跳出多次嵌套的循环:
for n in a b c d e do while true do if [ $RANDOM -gt 20000 ];then printf . break 2 # 跳出while以及for循环 elif [ $RANDOM -lt 10000 ];then printf '"' break ## 仅跳出while循环 fi done done echo
(5) continue
for n in {1..9} do x=$RANDOM [ $x -le 20000 ] && continue echo "n=$n x=$x" done