Shell Script 结构化命令

if语句

if command
then
    command
fi

bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0,位于then部分的命令就会被执行。如果该命令的退出状态码是其他值, then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。fi语句用来表示if-then语句到此结束。

$ cat test2.sh
#!/bin/bash
if IamNotaCommand
then
    echo "It worked"
fi
echo "We are outside the if statement"
$
$ ./test2.sh
./test2.sh: line 3: IamNotaCommand: command not found
We are outside the if statement
$

if-then-else语句,当if语句中的命令返回非零退出状态码时,bash shell会执行else部分中的命令。 

if command
then
    commands
else
    commands
fi

有时你需要检查脚本代码中的多种条件。对此,可以使用嵌套的if-then语句。嵌套的if-then语句位于主if-then-else语句的else代码块中。可以使用else部分的另一种形式:elif。elif使用另一个if-then语句延续else部分。

if command1
then
    commands
elif command2
then
    more commands
fi
  • test命令

test命令提供了在if-then语句中测试不同条件的途径。如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。这样if-then语句就与其他编程语言中的if-then语句以类似的方式工作了。如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得if-then语句不会再被执行。

if test condition
then
    commands
fi

如果不写test命令的condition部分,它会以非零的退出状态码退出,并执行else语句块。当你加入一个条件时,test命令会测试该条件,当my_variable=""时,输出False

#!/bin/bash
my_variable="Full"
if test $my_variable
then
    echo "True"
else
    echo "False"
fi
$ ./test6.sh
True
$

bash shell提供了另一种条件测试方法,无需在if-then语句中声明test命令。方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。

if [ condition ]
then
    commands
fi
  • 数值比较
test命令的数值比较功能
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
  • 字符串比较
字符串比较
str1 = str2 检查str1和str2是否相同
str1 != str2 检查str1和str2是否不同
str1 < str2 检查str1是否比str2小
str1 > str2 检查str1是否比str2大
-n str1  检查字符串长度是否非0
-z str1 检查字符串长度是否为0

要测试一个字符串是否比另一个字符串大或小时,大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名;

if [ $val1 \> $val2 ]
  • 文件比较
文件比较功能
-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旧
  • 布尔逻辑运算

  • [ condition1 ] && [ condition2 ]:AND
  • [ condition1 ] || [ condition2 ]:OR
  • 双括号用于数学表达式

双括号命令允许你在比较过程中使用高级数学表达式。test命令只能在比较中使用简单的算术操作。双括号命令的格式如下:expression可以是任意的数学赋值或比较表达式不需要将双括号中表达式里的大于号转义

(( expression ))
双括号命令符号
val++ 后增
val-- 后减
++val 先增
--val 先减
逻辑求反
~ 按位求反
** 幂运算
<< 左位移
>> 右位移
& 按位布尔和运算
| 按位布尔或运算
&& 逻辑和
|| 逻辑或
$ cat test23.sh
#!/bin/bash
val1=10
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi
$ ./test23.sh
The square of 10 is 100
$
  • 双方括号用于高级字符串处理

双方括号命令提供了针对字符串比较的高级特性。双方括号里的expression使用了test命令中采用的标准字符串比较。但它提供了test命令未提供的另一个特性——模式匹配。

[[ expression ]]

使用了双等号(==)。双等号将右边的字符串(r*)视为一个模式,并应用模式匹配规则。双方括号命令$USER环境变量进行匹配,看它是否以字母r开头 

$ cat test24.sh
#!/bin/bash
if [[ $USER == r* ]]
then
    echo "Hello $USER"
else
    echo "Sorry, I do not know you"
fi
$ ./test24.sh
Hello rich
$
  • case命令

在一组可能的值中寻找特定值,不得不写出很长的if-then-else语句。

$ cat test25.sh
#!/bin/bash
if [ $USER = "rich" ]
then
    echo "Welcome $USER"
    echo "Please enjoy your visit"
elif [ $USER = "barbara" ]
then
    echo "Welcome $USER"
    echo "Please enjoy your visit"
elif [ $USER = "testing" ]
then
    echo "Special testing account"
elif [ $USER = "jessica" ]
then
    echo "Do not forget to logout when you're done"
else
    echo "Sorry, you are not allowed here"
fi

case命令会采用列表格式来检查单个变量的多个值。可以通过竖线操作符在一行中分隔出多个模式模式。星号会捕获所有与已知模式不匹配的值。

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac
$ cat test26.sh
#!/bin/bash
case $USER in
rich | 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, you are not allowed here";;
esac

for语句

for var in list
do
    commands
done
  • 读取列表中的复杂值

在遍历带有单引号的字符串时,shell看到了列表值中的单引号并尝试使用它们来定义一个单独的数据值。

$ cat badtest1
#!/bin/bash
for test in I don't know if this'll work
do
    echo "word:$test"
done
$ ./badtest1
word:I
word:dont know if thisll
word:work
$

有两种办法可解决这个问题: 使用转义字符(反斜线)来将单引号转义; 使用双引号来定义用到单引号的值。在第一个有问题的地方添加了反斜线字符来转义don't中的单引号。在第二个有问题的地方将this'll用双引号圈起来

$ cat test2
#!/bin/bash
for test in I don\'t know if "this'll" work
do
    echo "word:$test"
done
$ ./test2
word:I
word:don't
word:know
word:if
word:this'll
word:work
$

for命令用空格来划分列表中的每个值。如果在单独的数据值中有空格,就必须用双引号将这些值圈起来

for test in Nevada New Hampshire New Mexico New York North Carolina
for test in Nevada "New Hampshire" "New Mexico" "New York"
  • 从变量读取列表

list="Alabama Alaska Arizona Arkansas Colorado"
for state in $list
  • 从命令读取值

file="states"
for state in $(cat $file)
  • 更改字段分隔符

默认情况下,bash shell会将下列字符当作字段分隔符: 空格; 制表符; 换行符。可以在shell脚本中临时更改IFS环境变量的值来限制被bash shell当作字段分隔符的字符。例如,如果你想修改IFS的值,使其只能识别换行符,

IFS=$'\n'
for state in $(cat $file)
  • 用通配符读取目录

用for命令来自动遍历目录中的文件。进行此操作时,必须在文件名或路径名中使用通配符。它会强制shell使用文件扩展匹配。

for file in /home/rich/test/*
do
  • C 语言风格的for 命令

bash shell支持一种for循环,它看起来跟C语言风格的for循环类似,但有一些细微的不同

for (( variable assignment ; condition ; iteration process ))
$ cat test8
#!/bin/bash
# testing the C-style for loop
for (( i=1; i <= 10; i++ ))
do
    echo "The next number is $i"
done

C语言风格的for命令也允许为迭代使用多个变量 

for (( a=1, b=10; a <= 10; a++, b-- ))
do
    echo "$a - $b"
done

while

while命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的是退出状态码0。它会在每次迭代的一开始测试test命令。在test命令返回非零退出状态码时,while命令会停止执行那组命令。

while test command
do
    other commands
done

while命令的关键在于所指定的test command的退出状态码必须随着循环中运行的命令而改变。如果退出状态码不发生变化, while循环就将一直不停地进行下去。

while [ $var1 -gt 0 ]
do
    echo $var1
    var1=$[ $var1 - 1 ]
done

while命令允许你在while语句行定义多个测试命令。只有最后一个测试命令的退出状态码会被用来决定什么时候结束循环。 

until 

until命令要求你指定一个通常返回非零退出状态码的测试命令。只有测试命令的退出状态码不为0,bash shell才会执行循环中列出的命令。一旦测试命令返回了退出状态码0,循环就结束了。

until test commands
do
    other commands
done
var1=100
until [ $var1 -eq 0 ]
do
    echo $var1
    var1=$[ $var1 - 25 ]
done

循环处理文件数据

通过修改IFS环境变量,就能强制for命令将文件中的每行都当成单独的一个条目来处理,即便数据中有空格也是如此。一旦从文件中提取出了单独的行,可能需要再次利用循环来提取行中的数据。

#!/bin/bash
IFS.OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)  #命令输出赋值
do
    echo "Values in $entry –"
    IFS=:
    for value in $entry
    do
        echo " $value"
    done
done
$

处理循环的输出

在shell脚本中,可以对循环的输出使用管道或进行重定向。

for file in /home/rich/*
do
    if [ -d "$file" ]
    then
        echo "$file is a directory"
    elif
        echo "$file is a file"
    fi
done > output.txt

查找可执行文件

当你从命令行中运行一个程序的时候,Linux系统会搜索一系列目录来查找对应的文件。这些目录被定义在环境变量PATH中。如果你想找出系统中有哪些可执行文件可供使用,只需要扫描PATH环境变量中所有的目录就行了。

$ cat test25
#!/bin/bash
IFS=:
for folder in $PATH
do
    echo "$folder:"
    for file in $folder/*
    do
        if [ -x $file ]
        then
            echo " $file"
        fi
    done
done
$

猜你喜欢

转载自blog.csdn.net/linshuo1994/article/details/84103670