if-then 语句
# 如果 if 后面的 command 的退出状态码是 0,执行 then 后面的命令if commandthencommandsfi# 或者if command; thencommandsfiif grep $testuser /et/passwdthen...fi#!/bin/bashDIR="/media/cdrom"if [ ! -e $DIR ]thenmkdir -p $DIRfi
if-then-else
if commandthencommandselsecommandsfiif commandthencommandselif commandthencommandsfi#!/bin/bashping -c 3 -i 0.2 -W 3 $1 &> /dev/nullif [ $? -eq 0 ]thenecho "Host $1 is On-line."elseecho "Host $1 is Off-line."fi
示例:
# 使用 if...elifif grep $testuser /etc/passwdthenecho "The user $testuser exists on this system."elif ls -d /home/$testuserthenecho "The user $testuser does not exist on this system."echo "However, $testuser has a directory."elseecho "The user $testuser does not exist on this system."echo "However, $testuser does not have a directory."fi#!/bin/bashread -p "Enter your score( 0-100): " GRADEif [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; thenecho "$GRADE is Excellent"elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; thenecho "$GRADE is Pass"elseecho "$GRADE is Fail"fi
test 命令
# test 命令没有命令的话,以非零的退出状态码退出if testthenecho "test command is ok."elseecho "test command is false."fi# 可以使用 test 命令确定变量中是否有内容my_variable="23"if test $my_variablethenecho "variable is not empty."elseecho "variable is empty."fi
使用方括号定义测试条件,第一个方括号之后和第二个方括号之前必须有空格:
- 数值比较
- 字符串比较
- 文件比较
数值比较
n1 -eq n2
n1 -ge n2
n1 -gt n2
n1 -le n2
n1 -lt n2
n1 -ne n2
# 方括号前后必须要有空格# test 命令中不能使用浮点数if [ $value1 -gt $value2 ]thenecho "$value1 is greater than $value2"elif [ $value1 -lt $value2 ]thenecho "$value1 is less than $value2"elseecho "$value1 is equal $value2"fiechoFreeMem=`free -m | grep Mem: | awk '{print $4}'`[ $FreeMem -lt 1024 ] && echo "Insufficient Memory"
字符串比较
str1 = str2
str1 != str2
str1 < str2
str1 > str2
-n str1 检查 str1 的长度是否非0
-z str1 检查 str1 的长度是否为0
注意,字符串顺序比较中:
- 大于号和小于号必须转义
- 大于和小于顺序和 sort 命令所采用的不同
在比较测试中,大写字母被认为是小于小写字母的。而 sort 命令相反。
比较测试中用的是标准的 ASCII 顺序。sort 命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺序中小写字母出现在大写字母前。
if [ $USER != $testuser ]then...fiif [ $var1 \> $var2 ]then...fi[ $LANG != "en.US" ] && echo "Not en.US"
文件比较
-d file测试文件是否为目录类型
-f file判断是否为一般文件
-e file测试文件是否存在
-r file测试当前用户是否有权限读取
-w file测试当前用户是否有权限写入
-x file测试当前用户是否有权限执行
-O file 检查 file 是否存在并属于当前用户所有
-G file 检查 file 是否存在并且默认组与当前用户相同
-s file 检查 file 是否存在并非空
file1 -nt file2
file1 -ot file2
使用 -nt 或 -ot 比较文件之前,最后先检查文件是否存在:
# 文件不存在,返回 falseif [ badfile1 -nt badfile2 ]thenecho "The badfile1 file is newer than badfile2"elseecho "The badfile1 file is older than badfile2"fi# 结果是The badfile1 file is older than badfile2
复合条件测试
[ condition1 ] || [ condition2 ][ condition1 ] && [ condition2 ][ ! $USER = root ] || echo "administrator"
双括号和双方括号
双括号里面可以进行算数运算。
双方括号里面可以进行字符串处理。
记住,不管是方括号还是双方括号,都需要有空格。而单括号的命令替换和双括号的算数运算,不需要有空格。
# 双括号里面不需要使用 $if ((val1 ** 2 > 90))then# 赋值时 = 两边可以有空格((val2 = val1 ** 2))echo "The square of $val1 is $val2"fi# 方括号两边必需要有空格,模式匹配功能if [[ $USER == x* ]]thenecho "Hello $USER."elseecho "Sorry, I do not know you."fi
case 命令
case variable inpattern1 | pattern2) commands1;;pattern3) commands2;;*) default commands;;esac
注意结尾的双分号
case $USER inxiaocan | barbara)echo "Welcome, $USER"echo "Please enjoy your visit.";;testing)echo "Special testing account.";;jessica)echo "Do not forget to log off when you're done.";;*)echo "Sorry, your are not allowed here";;esac#!/bin/bashread -p "请输入一个字符,并按 Enter 键确认: " KEYcase "$KEY" in[a-z]|[A-Z])echo "您输入的是 字母。 ";;[0-9])echo "您输入的是 数字。 ";;*)echo "您输入的是 空格、功能键或其他控制字符。 "esac
for 命令
for var in listdocommanddone
示例:
for test in Alabama Alaska Arizona Arkasas Californiadoecho The next state is $testdone# 不同于其他编程语言,在 for 循环结束后,也能够使用 test 变量echo $test# 对单引号转义,或者使用双引号包括它for test in I don\'t know if "this'll" workdoecho "word: $test"done# 使用双引号包括多个词汇for test in Nevada "New Hampshire" "New York"doecho "City: $test"done# 字符串拼接的常用方法list=$list" Connecticut"# 怎么打印带有空格的字符呢?files="states"# 更新字段的分割符IFS=$'\n'for state in $(cat $files)doecho "Visit beautiful $state"done
for 循环假定每个值都是空格分割的。使用 IFS (内部字段分隔符 internal field separator)指定分隔符。
IFS.OLD=$IFSIFS=$'\n'# 之后再还原 IFS 的值IFS=$IFS.OLDIFS=:# 换行符、冒号、分号、双引号IFS=$'\n':;"
读取目录:
# 可以指定多个目录for file in /Users/xiaocan/Documents/learn/shell-learn/* /home/rich/badtestdo# 防止 file 名称有空格,所以添加引号if [ -d "$file" ]thenecho "$file is a directory."elif [ -f "$file" ]thenecho "$file is a file."fidone

批量 ping 主机:
#!/bin/bashHLIST=$(cat ~/ipadds.txt)for IP in $HLISTdoping -c 3 -i 0.2 -W 3 $IP &> /dev/nullif [ $? -eq 0 ] ; thenecho "Host $IP is On-line."elseecho "Host $IP is Off-line."fidone
C 语言风格的 for 命令
# 括号两边的空格不是必需的for (( i = 1; i <= 10; i++ ))doecho "The next number is $i"doneechofor (( a=1, b=10; a <= 10; a++, b--))doecho "$a - $b"done
while 命令
while test commanddocommandsdone
示例:
var1=10while [ $var1 -gt 0 ]doecho $var1var1=$(( var1 - 1 ))doneechovar1=5# 多个测试命令# 只有最后一个命令成立时才会停止。如果互换了下面两条命令的位置,就一直循环下去了while echo $var1[ $var1 -gt 0 ]doecho "This is inside the loop"var1=$(( var1 - 1 ))done
猜数字游戏:
猜数字游戏#!/bin/bashPRICE=$(expr $RANDOM % 1000)TIMES=0echo "商品实际价格为 0-999 之间,猜猜看是多少? "while truedoread -p "请输入您猜测的价格数目: " INTlet TIMES++if [ $INT -eq $PRICE ] ; thenecho "恭喜您答对了,实际价格是 $PRICE"echo "您总共猜 g $TIMES 次"exit 0elif [ $INT -gt $PRICE ] ; thenecho "太高了! "elseecho "太低了! "fidone
until 命令
until test commanddocommandsdone
示例:
var1=100until [ $var1 -eq 0 ]doecho $var1var1=$(( var1 - 25 ))doneecho# 使用多个测试命令var1=100until echo $var1[ $var1 -eq 0 ]doecho Inside the loop.var1=$(( var1 - 25 ))done
break 和 continue
和编程语言中的 break 和 continue 类似,不同的是,在 shell 中它们后面可以跟一个数字,指定跳出的层数。
# 注意在 while 中使用 continue,下面的例子不会结束var2=1while [ $var2 -lt 15 ]doif [ $var2 -gt 5 ] && [ $var2 -lt 10 ]thencontinuefiecho "The value is $var2"var2=$((var2+1))done
处理循环的输出
可以在 done 命令之后添加一个处理命令。
# 在 done 后面使用管道或重定向命令for state in "North Dakata" Connecticut Illinois Alabama Tennesseedoecho "The state is $state"done | sort# 或者# done > test.txt
