赞
踩
最基本的结构化命令是 if-then 语句。if-then 语句的格式如下:
if command then commands if if command; then # 通过把分号(;)放在待求值的命令尾部,可以将 then 语句写在同一行 commands if
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
bash shell 的 if 语句会运行 if 之后的命令。如果该命令的退出状态码(参见第 11 章)为 0(命令成功运行),那么位于 then 部分的命令就会被执行。如果该命令的退出状态码是其他值,则 then 部分的命令不会被执行,bash shell 会接着处理脚本中的下一条命令。fi 语句用来表示if-then 语句到此结束。
#!/bin/bash # testing the if statement if pwd # if 行中的 pwd 命令,由于退出状态码是 0,会执行if-then 内部的语句 then echo 'heheh' if
- 1
- 2
- 3
- 4
- 5
- 6
#!/bin/bash # testing an incorrect command if IamNotCommand # if 行中的 IamNotCommand 命令,由于命令不存在,不会执行if-then 内部的语句 then echo 'heheh' if
- 1
- 2
- 3
- 4
- 5
- 6
if-then-else 语句在语句中提供了另外一组命令
if command then commands else commands if
- 1
- 2
- 3
- 4
- 5
- 6
#!/bin/bash # testing the else section # testuser=NoSuchUser # if grep $testuser /etc/passwd then echo "The script files in the home directory of $testuser are:" ls /home/$testuser/*.sh echo else echo "The user $testuser does not exist on this system." echo fi echo "We are outside the if statement"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
elif 语句行提供了另一个要测试的命令,这类似于原始的 if 语句行。
if command1 then commands elif command2 then more commands fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
test 命令可以在 if-then 语句中测试不同的条件。如果 test 命令中列出的条件成立,那么test 命令就会退出并返回退出状态码 0。如果条件不成立,那么 test 命令就会退出并返回非 0 的状态码,这使得 if-then 语句不会再被执行。
test 命令的格式非常简单:
test condition if test condition then commands fi
- 1
- 2
- 3
- 4
- 5
如果不写 test 命令的 condition 部分,则它会以非 0 的退出状态码退出。
使用 test 命令确定变量中是否为空:
#!/bin/bash # testing if a variable has content # my_variable="Full" # if test $my_variable # my_variable不是空,返回状态0 then echo "The my_variable variable has content and returns a True." echo "The my_variable variable content is: $my_variable" else echo "The my_variable variable doesn't have content," echo "and returns a False." fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
bash shell 提供了另一种条件测试方式,无须在 if-then 语句中写明 test 命令:
if [ condition ] then commands fi
- 1
- 2
- 3
- 4
方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须留有空格,否则就会报错。
test 命令和测试条件可以判断 3 类条件:
数值比较(注意:不支持浮点数,只能用于整数)
字符串比较
文件比较
比较 | 描述 |
---|---|
n1 -eq n2 | 检查 n1 是否等于 n2 |
n1 -ge n2 | 检查 n1 是否大于或等于 n2 |
n1 -gt n2 | 检查 n1 是否大于 n2 |
n1 -le n2 | 检查 n1 是否小于或等于 n2 |
n1 -lt n2 | 检查 n1 是否小于 n2 |
n1 -ne n2 | 检查 n1 是否不等于 n2 |
#!/bin/bash # Using numeric test evaluations # value1=10 value2=11 # if [ $value1 -gt 5 ] then echo "The test value $value1 is greater than 5." fi # if [ $value1 -eq $value2 ] then echo "The values are equal." else echo "The values are different." fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
比较 | 描述 |
---|---|
str1 = str2 | 检查 str1 是否和 str2 相同 |
str1 > str2 | 检查 str1 是否大于 str2 |
str1 < str2 | 检查 str1 是否小于 str2 |
str1 != str2 | 检查 str1 是否和 str2 不同 |
-n str1 | 检查 str1 的长度是否不为 0 |
-z str1 | 检查 str1 的长度是否为 0 |
#!/bin/bash # Using string test evaluations # testuser=christine # if [ $testuser = christine ] then echo "The testuser variable contains: christine" else echo "The testuser variable contains: $testuser" fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
比较 | 描述 |
---|---|
-d file | 检查 file 是否存在且为目录 |
-e file | 检查 file 是否存在 |
-f file | 检查 file 是否存在且为文件 |
-r file | 检查 file 是否存在且可读 |
-s file | 检查 file 是否存在且非空 |
-w file | 检查 file 是否存在且可写 |
-x file | 检查 file 是否存在且可执行 |
-O file | 检查 file 是否存在且属当前用户所有 |
-G file | 检查 file 是否存在且默认组与当前用户相同 |
file1 -nt file2 | 检查 file1 是否比 file2 新 |
file1 -ot file2 | 检查 file1 是否比 file2 旧 |
#!/bin/bash # 检查目录 # jump_directory=/home/Torfa # if [ -d $jump_directory ] then echo "The $jump_directory directory exists." cd $jump_directory ls else echo "The $jump_directory directory does NOT exist." fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在子 shell 中执行命令的单括号
用于数学表达式的双括号
用于高级字符串处理功能的双方括号
单括号允许在 if 语句中使用子 shell。单括号形式的 test 命令格式如下:
(command)
- 1
在 bash shell 执行 command 之前,会先创建一个子 shell,然后在其中执行命令。如果命令成功结束,则退出状态码会被设为 0,then 部分的命令就会被执行。
#!/bin/bash # Testing a single parentheses condition # echo $BASH_SUBSHELL # if (echo $BASH_SUBSHELL) then echo "The subshell command operated successfully." # else echo "The subshell command was NOT successful." # fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
当脚本第一次(在 if 语句之前)执行 echo $BASH_SUBSHELL 命令时,是在当前 shell 中完成的。该命令会输出 0,表明没有使用子 shell($BASH_SUBSHELL :当前子 shell 环境的嵌套级别(初始值是 0))。在if 语句内,脚本在子 shell 中执行 echo $BASH_SUBSHELL 命令,该命令会输出 1,表明使用了子 shell。子 shell 操作成功结束,接下来是执行 then 部分的命令
双括号命令允许在比较过程中使用高级数学表达式。
符号 | 描述 |
---|---|
val++ | 后增 |
val– | 后减 |
++val | 先增 |
–val | 先减 |
! | 逻辑求反 |
- | 位求反 |
** | 幂运算 |
<< | 左位移 |
>> | 右位移 |
& | 位布尔 AND |
&& | 逻辑 AND |
| | 逻辑OR |
#!/bin/bash # Testing a double parentheses command # val1=10 # if (( $val1 ** 2 > 90 )) then (( val2 = $val1 ** 2 )) echo "The square of $val1 is $val2," echo "which is greater than 90." # fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
双方括号命令提供了针对字符串比较的高级特性。双方括号的格式如下:
[[ expression ]]
- 1
expression 可以使用 test 命令中的标准字符串比较。除此之外,它还提供了 test 命令所不具备的另一个特性——模式匹配。
在进行模式匹配时,可以定义通配符或正则表达式
#!/bin/bash # Using double brackets for pattern matching # # if [[ $BASH_VERSION == 5.* ]] then echo "You are using the Bash Shell version 5 series." fi # 上述脚本中使用了双等号(==)。双等号会将右侧的字符串(5.*)视为一个模式并应用模式匹配规则。 # 双方括号命令会对$BASH_VERSION 环境变量进行匹配,看是否以字符串 5.起始。 # 如果是,则测试通过,shell 会执行 then 部分的命令。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
有了 case 命令,无须再写大量的 elif 语句来检查同一个变量的值了。case 命令会采用列表格式来检查变量的多个值:
case variable in pattern1 | pattern2) commands1;; pattern3) commands2;; *) default commands;; esac
- 1
- 2
- 3
- 4
- 5
#!/bin/bash # Using a short case statement # case $USER in rich | christine) echo "Welcome $USER" echo "Please enjoy your visit.";; barbara | tim) echo "Hi there, $USER" echo "We're glad you could join us.";; testing) echo "Please log out when done with test.";; *) echo "Sorry, you are not allowed here." esac $
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
bash shell 提供了 for 命令,以允许创建遍历一系列值的循环。每次迭代都使用其中一个值来执行已定义好的一组命令。for 命令的基本格式如下:
for var in list do commands done
- 1
- 2
- 3
- 4
#!/bin/bash # basic for command 读取列表中的值 for test in Alabama Alaska Arizona Arkansas California Colorado do echo The next state is $test done
- 1
- 2
- 3
- 4
- 5
- 6
for 命令使用空格来划分列表中的每个值。如果某个值含有空格,则必须将其放入双引号内
#!/bin/bash # an example of how to properly define values for test in Nevada "New Hampshire" "New Mexico" "New York" do echo "Now going to $test" done
- 1
- 2
- 3
- 4
- 5
- 6
#!/bin/bash # using a variable to hold the list list="Alabama Alaska Arizona Arkansas Colorado" list=$list" Connecticut" for state in $list # do echo "Have you ever visited $state?" done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
$list 变量包含了用于迭代的值列表。注意,脚本中还使用了另一个赋值语句向$list 变量包含的值列表中追加(或者说是拼接)了一项。这是向变量中已有的字符串尾部添加文本的一种常用方法。
#!/bin/bash # reading values from a file file="states.txt" for state in $(cat $file) do echo "Visit beautiful $state" done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
使用 cat 命令来输出文件 states.txt 的内容,states.txt 文件中每
个值各占一行,而不是以空格分隔。
IFS环境变量定义了 bash shell 用作字段分隔符的一系列字符。在默认情况下,bash shell 会将下列字
符视为字段分隔符:
空格
制表符
换行符
如果 bash shell 在数据中看到了这些字符中的任意一个,那么它就会认为这是列表中的一个新字段的开始。
可以在 shell 脚本中临时更改 IFS 环境变量的值,指定字段分隔符的字符。
#!/bin/bash # reading values from a file file="states.txt" IFS.OLD=$IFS IFS=$'\n' # 告诉 bash shell 忽略数据中的空格和制表符 for state in $(cat $file) do echo "Visit beautiful $state" done IFS=$IFS.OLD # 恢复默认值,保证后续使用默认值的操作能正常运行 # IFS=: # 如果要遍历文件中以冒号分隔的值,则只需将 IFS 的值设为冒号即可 # IFS=$'\n:;"' # 将换行符、冒号、分号和双引号作为字段分隔符
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
#!/bin/bash # iterate through all the files in a directory for file in /home/rich/test/* do if [ -d "$file" ] then echo "$file is a directory" elif [ -f "$file" ] then echo "$file is a file" fi done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
#!/bin/bash # 可以在 for 命令中列出多个目录通配符 for file in /home/rich/.b* /home/rich/badtest do if [ -d "$file" ] then echo "$file is a directory" elif [ -f "$file" ] then echo "$file is a file" else echo "$file doesn't exist" fi done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
bash 中仿 C 语言的 for 循环的基本格式如下:
for (( variable assignment ; condition ; iteration process )) # demo for (( a = 1; a < 10; a++ ))
- 1
- 2
- 3
- 4
注意,有些地方与 bash shell 标准的 for 命令并不一致:
变量赋值可以有空格
迭代条件中的变量不以美元符号开头
迭代过程的算式不使用 expr 命令格式
#!/bin/bash # testing the C-style for loop for (( i=1; i <= 10; i++ )) do echo "The next number is $i" done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
仿 C 语言的 for 命令也允许为迭代使用多个变量
#!/bin/bash # multiple variables for (( a=1, b=10; a <= 10; a++, b-- )) do echo "$a - $b" done
- 1
- 2
- 3
- 4
- 5
- 6
while 命令在某种程度上糅合了 if-then 语句和 for 循环。while 命令的格式如下:
while test command do other commands done
- 1
- 2
- 3
- 4
while 命令中定义的 test command 与 if-then 语句中的格式一模一样。可以使用任何 bash shell 命令,或者用 test command 进行条件测试。
while 命令的关键在于所指定的 test command 的退出状态码必须随着循环中执行的命令而改变。如果退出状态码不发生变化,那 while 循环就成了死循环。
#!/bin/bash # while command test var1=10 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
while 命令允许在 while 语句行定义多个测试命令。只有最后一个测试命令的退出状态码会被用于决定是否结束循环。
#!/bin/bash # testing a multicommand while loop var1=10 while echo $var1 [ $var1 -ge 0 ] do echo "This is inside the loop" var1=$[ $var1 - 1 ] done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
与 while 命令工作的方式完全相反,until 命令要求指定一个返回非 0 退出状态码的测试命令。只要测试命令的退出状态码不为 0,bash shell 就会执行循环中列出的命令。一旦测试命令返回了退出状态码 0,循环就结束了。
until test command do other commands done
- 1
- 2
- 3
- 4
break 命令是退出循环的一种简单方法。你可以用 break 命令退出任意类型的循环,包括while 循环和 until 循环。
#!/bin/bash # breaking out of a for loop for var1 in 1 2 3 4 5 6 7 8 9 10 do if [ $var1 -eq 5 ] then break fi echo "Iteration number: $var1" done echo "The for loop is completed"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在处理多个循环时,break 命令会自动结束你所在的最内层循环:
#!/bin/bash # breaking out of an inner loop for (( a = 1; a < 4; a++ )) do echo "Outer loop: $a" for (( b = 1; b < 100; b++ )) do if [ $b -eq 5 ] then break # 结束内层循环 fi echo " Inner loop: $b" done done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
有时你位于内层循环,但需要结束外层循环。break 命令接受单个命令行参数:
break n
- 1
其中 n 指定了要跳出的循环层级。在默认情况下,n 为 1,表明跳出的是当前循环。如果将 n 设为 2,那么 break 命令就会停止下一级的外层循环:
#!/bin/bash # breaking out of an outer loop for (( a = 1; a < 4; a++ )) do echo "Outer loop: $a" for (( b = 1; b < 100; b++ )) do if [ $b -gt 4 ] then break 2 # 结束外层循环 fi echo " Inner loop: $b" done done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
continue 命令可以提前中止某次循环,但不会结束整个循环。你可以在循环内部设置 shell不执行命令的条件。
#!/bin/bash # using the continue command for (( var1 = 1; var1 < 15; var1++ )) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
也可以在 while 循环和 until 循环中使用 continue 命令,但要特别小心。记住,当 shell执行 continue 命令时,它会跳过剩余的命令
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。