基础shell小技巧002

1. 使用if-then语句

如果之前用过其他编程语言的if-then语句,那么这种形式可能会让你有点儿困惑。在其他编程语言中,if语句之后的对象是一个等式,其求值结果为TRUE或FALSE。但bash shell的if语句并非如此。

重点:bash shell的if语句会运行if之后的命令。如果该命令的退出状态码为0(命令成功运行),那么位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,则then部分的命令不会被执行,bash shell会接着处理脚本中的下一条命令。fi语句用来表示if-then语句到此结束。

# !/bin/bash

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

2. test命令

test命令可以在if-then语句中测试不同的条件。如果test命令中列出的条件成立,那么test命令就会退出并返回退出状态码0。这样if-then语句的工作方式就和其他编程语言中的if-then语句差不多了。如果条件不成立,那么test命令就会退出并返回非0的退出状态码,这使得if-then语句不会再被执行。

test命令的格式非常简单:

test condition

demo:

# !/bin/bash
my_variable=""

if test $my_variable
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

bash shell提供了另一种条件测试方式,无须在if-then语句中写明test命令:

if [ condition ]
then
   commands
fi
# 方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须留有空格,否则就会报错。

test命令和测试条件可以判断3类条件:

  1. 数值比较
  2. 字符串比较
  3. 文件比较

2.1 数值比较

比较 描述
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
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

注意:对于条件测试,bash shell只能处理整数。尽管可以将浮点值用于某些命令(比如echo),但它们在条件测试下无法正常工作。

2.2 字符串比较

比较 描述
str1 = str2 检查str1是否和str2相同
str1 != str2 检查str2是否和str2不同
str1 < str2 检查str2是否小于str2
str1 > str2 检查str2是否大于str2
-n str1 检查str1的长度是否不为0
-z str1 检查str1的长度是否为0

字符串的相等和不等条件不言自明,很容易看出两个字符串值是否相同:

# !/bin/bash

testuser=christine
#
if [ $testuser = christine ]
then
     echo "The testuser variable contains: christine"
else
     echo "The testuser variable contains: $testuser"
fi

要测试一个字符串是否大于或小于另一个字符串就开始变得棘手了。使用测试条件的大于或小于功能时,会出现两个经常困扰shell程序员的问题。·大于号和小于号必须转义,否则shell会将其视为重定向符,将字符串值当作文件名。

# !/bin/bash

string1=soccer
string2=zorbfootball

if [ $string1 \> $string2 ]
then
     echo "$string1 is greater than $string2"
else
     echo "$string1 is less than $string2"
fi

-n和-z可以很方便地用于检查一个变量是否为空:

# !/bin/bash
string1=Soccer
string2=''
#
if [ -n $string1 ]
then
     echo "The string '$string1' is NOT empty"
else
     echo "The string '$string1' IS empty"
fi
#
if [ -z $string2 ]
then
     echo "The string '$string2' IS empty"
else
     echo "The string '$string2' is NOT empty"
fi
#
if [ -z $string3 ]
then
     echo "The string '$string3' IS empty"
else
     echo "The string '$string3' is NOT empty"
fi

2.3文件比较

比较 描述
-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旧

-d测试会检查指定的目录是否存在于系统中。如果打算将文件写入目录或是准备切换到某个目录,那么先测试一下总是件好事:

# !/bin/bash

jump_directory=$(pwd)
#
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

3. 复合条件测试

if-then语句允许使用布尔逻辑将测试条件组合起来。可以使用以下两种布尔运算符。

  • [ condition1 ] && [ condition2 ] :第一种布尔运算使用布尔运算符AND来组合两个条件。要执行then部分的命令,两个条件都必须满足。
  • [ condition1 ] || [ condition2 ]:第二种布尔运算使用OR布尔运算符来组合两个条件。如果任意条件为真,那么then部分的命令就会执行。
# !/bin/bash
echo $HOME
if [ -d $HOME ] && [ -w $HOME/newfile ]
then
     echo "The file exists and you can write to it."
#
else
     echo "You cannot write to the file."
#
fi

4. if-then的高级特性

bash shell还提供了3个可在if-then语句中使用的高级特性。·

  • 在子shell中执行命令的单括号。

  • 用于数学表达式的双括号。

  • 用于高级字符串处理功能的双方括号。

接下来将详细描述各个特性。

4.1 使用单括号

在bash shell执行command之前,会先创建一个子shell,然后在其中执行命令。如果命令成功结束,则退出状态码(参见第11章)会被设为0,then部分的命令就会被执行。如果命令的退出状态码不为0,则不执行then部分的命令。来看一个使用子shell进行测试的例子:

# !/bin/bash

echo $BASH_SUBSHELL
if (echo $BASH_SUBSHELL)
then
     echo "The subshell command operated successfully."
#
else
     echo "The subshell command was NOT successful."
#
fi

4.2 使用双括号

双括号命令允许在比较过程中使用高级数学表达式。test命令在进行比较的时候只能使用简单的算术操作。双括号命令提供了更多的数学符号,这些符号对有过其他编程语言经验的程序员而言并不陌生。双括号命令的格式如下:

(( expression ))

双括号命令符号:

符号 描述
val++ 后增
val– 后减
++val 先增
–val 先减
逻辑求反
~ 位求反
** 幂运算
<< 左位移
>> 右位移
& 位布尔AND
| 位布尔OR
&& 逻辑AND
|| 逻辑OR

双括号命令既可以在if语句中使用,也可以在脚本中的普通命令里用来赋值:

# !/bin/bash

val1=10
#
if (( $val1 ** 2 > 90 ))
then
    (( val2 = $val1 ** 2 ))
    echo "The square of $val1 is $val2,"
    echo "which is greater than 90."
#
fi

4.3 使用双括号

双方括号命令提供了针对字符串比较的高级特性。双方括号的格式如下:

[[ expression ]]

expression可以使用test命令中的标准字符串比较。除此之外,它还提供了test命令所不具备的另一个特性——模式匹配。

在进行模式匹配时,可以定义通配符或正则表达式匹配字符串:

# !/bin/bash
echo $BASH_VERSION

if [[ $BASH_VERSION == 4.* ]]
then
     echo "You are using the Bash Shell version 5 series."
fi

5. case命令

有了case命令,就无须再写大量的elif语句来检查同一个变量的值了。case命令会采用列表格式来检查变量的多个值:

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

case命令会将指定变量与不同模式进行比较。如果变量与模式匹配,那么shell就会执行为该模式指定的命令。你可以通过竖线运算符在一行中分隔出多个模式。星号会捕获所有与已知模式不匹配的值。下面是一个将if-then-else程序转换成使用case命令的例子:

# !/bin/bash

user="tim"

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

你可能感兴趣的:(Shell,linux,bash)