美文网首页
【Linux 基础】五、结构化命令

【Linux 基础】五、结构化命令

作者: 佳奥 | 来源:发表于2022-07-20 14:29 被阅读0次

1 if-then语句

if command
then
   commands
fi

例子一:
这个脚本在if行采用了pwd命令。如果命令成功结束,echo语句就会显示该文本字符串。

新建一个test1.sh

#!/bin/bash
#testing the if statement
if pwd
then
        echo "It Worked"
fi

$ chmod u+x test1.sh

输出结果:
$ ./test1.sh
/home/kaoku/data/shell_test
It Worked

例子二:
if语句行使用grep命令在/etc/passwd文件中查找某个用户名当前是否在系统上使用。如果有用户使用了那个登录名,脚本会显示一些文本信息并列出该用户HOME目录的bash文件。

#!/bin/bash
#testing multiple commands in the below section
#
testuser=kaoku
#
if grep $testuser /etc/passwd
then
        echo "This is my first command"
        echo "This is my second command"
        echo "I can even put in other commands besides echo:"
        ls -a /home/$testuser/.b*
fi

输出结果:
$ ./test3.sh
kaoku:x:1000:1000:kaoku:/home/kaoku:/bin/bash
This is my first command
This is my second command
I can even put in other commands besides echo:
/home/kaoku/.bash_history  /home/kaoku/.bash_logout 

如果将testuser变量设置成一个系统上不存在的用户,则什么都不会显示。

2 if-then-else语句

if command
then
  commands
else
  commands
fi

举个例子:
testuser=NosuchUser
if grep $testuser /etc/passwd
then
  echo "The bash files for user $testuser are:"
  ls -a /home/$testuser/.b*
  echo
else
  echo "The user $testuser does not exist"
  echo
fi

当if语句中的命令返回退出状态码0时,then部分中的命令会被执行,这跟普通的if-then语句一样。

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

3 嵌套if

要检查/etc/passwd文件中是否存在某个用户名以及该用户的目录是否尚在,可以使用嵌套的if-then语句:

testuser=NoSuchUser

if grep $testuser /etc/passwd
then
  echo "The user $testuser exist"
else
  echo "The user $testuser does not exist"
  if ls -d /home/$testuser/
  then
    echo "However, $testuser has a directory."
  fi
fi
这个脚本准确无误地发现,尽管登录名已经从/etc/passwd中删除了,但是该用户的目录仍然存在。

可以使用else部分的另一种形式:elif

if command1
then
  commands
elif commands
then
  more commands
fi

elif语句行提供了另一个要测试的命令,如果elif后命令的退出状态码是0,则bash会执行第二个then语句部分的命令。

testuser=NoSuchUser

if grep $testuser /etc/passwd
then
  echo "The user $testuser exist."

elif ls -d /home/$testuser
then
  echo "The user $testiser does not exist."
  echo "However, $testuser has a directory."
fi

甚至可以更进一步,让脚本检查拥有目录的不存在用户以及没有拥有目录的不存在用户。这可以通过在嵌套elif中加入一个else语句来实现。

testuser=NoSuchUser

if grep $testuser /etc/passwd
then
  echo "The user $testuser exist."

elif ls -d /home/$testuser
then
  echo "The user $testuser does not exist."
  echo "However, $testuser has a directory."

else
  echo "The user $testuser does not exist."
  echo "However, $testuser does not have a directory."
fi

窍门

在elif语句中,紧跟其后的else语句属于elif代码块。它们并不属于之前的if-then代码块。

可以继续将多个elif语句串起来,形成一个大的if-then-elif嵌套组合。

if command1
then
  command set1
elif command2
then
  command set2
fi

4 test命令

test命令提供了在if-then语句中测试不同条件的途径。

如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。这样if-then语句就与其他编程语言中的if-then语句以类似的方式工作了。

如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得if-then语句不会再被执行。

test命令格式:

test condition

用在if-then语句:

if test condition
then
  commands
fi

如果不写test命令的condition部分,它会以非零的退出状态码退出,并执行else语句块。

if test
then
  echo "No expression returns a True"
else
  echo "No expression returns a False"
fi

可以使用test命令确定变量中是否有内容。

my_variable="Full"

if test $my_variable
then
  echo "No expression returns a True"

else
  echo "No expression returns a False"
fi

变量my_variable中包含有内容(Full),因此当test命令测试条件时,返回的退出状态为0。这使得then语句块中的语句得以执行。

bash shell提供了另一种条件测试方法,无需在if-then语句中声明test命令。

if [condition]
then
  commands
fi

方括号定义了测试条件。

注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。

test命令可以判断的三类条件如下:

4.1 数值比较

test命令的数值比较功能:


image.png
value1=10
value2=11

if [ $value1 -gt 5 ]
then
  echo "The test value $value1 is greater than 2"
fi

if [ $value2 -eq $value2 ]
then
  echo "The value are equal"
else
  echo "The value are different"
fi

但是涉及浮点值时,数值条件测试会有一个限制。

如果value1=5.55,则不能在test命令中比较。bash shell只能处理整数。

4.2 字符串比较

字符串比较测试:


image.png

1字符串相等性

testuser=rich

if [ $USER = $testuser ]
then
  echo "Welcome $testuser"
fi

在比较字符串的相等性时,比较测试会将所有的标点和大小写情况都考虑在内。

2字符串顺序

为防止>被认成重定向保存文件,需要正确转义>符号。

val1=baseball
val2=hockey

if [ $val1 \> $val2 ]
then
  echo "$val1 is greater than $val2"
else
  echo "$val1 is less than $val2"
fi

在比较测试中,大写字母被认为是小于小写字母的。但sort命令恰好相反。

将同样的字符串放进文件中并用sort命令排序时,小写字母会先出现。

3字符串大小

-n和-z可以检查一个变量是否含有数据。

val1=testing
val2=''

if [ -n $val1 ]
then
  echo "The string '$val1' is not empty"
else
  echo "The string '$val1' is empty"
fi

if [ -z $val2 ]
then
 echo "The string '$val2' is not empty"
else
  echo "The string '$val2' is empty"
fi

The string 'testing' is not empty
The string '' is empty

4.3 文件比较

它允许我们测试Linux文件系统上文件和目录的状态。

test命令的文件比较功能:


image.png

1检查目录

jump_directory=/home/arthur

if [ -d $jump ]
then
  echo "The $jump_directory directory exists"
  cd $jump_directory
  ls
else
  echo "The $jump_directory directory does not exist"
fi

使用了-d测试条件来检查jump_directory变量中的目录是否存在:若存在,就使用cd命令切换到该目录并列出目录中的内容;若不存在,脚本就输出一条警告信息,然后退出。

2检查对象是否存在

location=$HOME
file_name="santine"
#
if [ -e $location ]
then #Directory does exist
  echo "OK on the $location directory."
  echo "Now checking on the file, $file_name."
  #
  if [ -e $location/$filename ]
  then #File does exist
    echo "OK on the filename"
    echo "Updating Current Date..."
    date >> $location/$filename
  #
    else #File does not exist
      echo "File does not exist"
      echo "Nothing to update"
    fi
#
else #Directory does not exist
  echo "The $location directory does not exist."
  echo "Nothing to update"
fi
#

第一次检查用-e比较来判断用户是否有HOME目录。如果有,接下来的-e比较会检查sentinel文件是否存在于$HOME目录中。

如果不存在,shell脚本就会提示该文件不存在,不需要进行更新。

为确保更新操作能够正常进行,我们创建了sentinel文件,然后重新运行这个shell脚本。这一次在进行条件测试时,$HOME和sentinel文件都存在,因此当前日期和时间就被追加到了文件中。

3检查文件

-e比较可用于文件和目录。要确定指定对象为文件,必须用-f比较。

item_name=$HOME
echo
echo "The item being checked:$item_name "
echo
#
if [ -e $item_name ]
then #Item does exist
  echo "The item, $item_name, does exist."
  echo "But is it a file?"
  echo
  #
  if [ -f $item_name ]
  then #Item os a file
    echo "Yes, $item_name is a file."
  #
  else #Item is not a file
    echo "No, $item_name is not a file."
  fi
#
else #Item dose not exist
  echo "The item, $item_name, does not exist."
  echo "Nothing to update"
fi

它首先使用-e比较测试$HOME是否存在。如果存在,继续用-f来测试它是不是一个文件。如果它不是文件,就会显示一条消息,表明这不是一个文件。

4检查是否可读

pwfile=/etc/shadow
#test if the file exists, and is a file
if [ -f $pwfile ]
then
  # now test if you can read it
  if [ -r $pwfile ]
  then
    tail $pefile
  else
    echo "Sorry, I am unable to read the $pwfile file"
    fi
else
  echo "Sorry, the file $file does not exist"
fi

5检查空文件

检查是否是文件
if [ -f $file_name ]
检查是否为空
if [ -s $file_name ]

6检查是否可写

if [ -w $file_name ]

7检查文件是否可执行

if [ -x test16.sh ]

8检查所属关系

if [ -O /etc/passwd ]

9检查文件日期

-nt比较会判定一个文件是否比另一个文件新。

如果文件较新,那意味着它的文件创建日期更近。

-ot比较会判定一个文件是否比另一个文件旧。

如果文件较旧,意味着它的创建日期更早。

5 复合条件测试

if-then语句允许我们使用布尔逻辑来组合测试。有两种布尔运算符可用:
 [ condition1 ] && [ condition2 ]
 [ condition1 ] || [ condition2 ]

第一种布尔运算使用AND布尔运算符来组合两个条件。要让then部分的命令执行,两个条件都必须满足。

第二种布尔运算使用OR布尔运算符来组合两个条件。如果任意条件为TRUE,then部分的命令就会执行。

下例展示了AND布尔运算符的使用:

if [ -d $HOME ] && [ -w $HOME/testing ]
then
  echo "The file exist and you can write it"
else
  echo "I cannot write to the file"
fi

6 if-then的高级特性

6.1 使用双括号

双括号命令的格式如下:

(( expression ))

双括号命令符号:


image.png

可以在if语句中用双括号命令,也可以在脚本中的普通命令里使用来赋值。**幂运算

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

The square of 10 is 100

注意,不需要将双括号中表达式里的大于号转义。这是双括号命令提供的另一个高级特性。

6.2 使用双方括号

双方括号命令的格式如下:

[[ expression ]]

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

if [[ $USER == r* ]]
then
  echo "Hello $USER"
else
  echo "Sorry, I do not know you"
fi

Hello rich

我们使用了双等号(==)。双等号将右边的字符串(r*)视为一个模式,并应用模式匹配规则。

双方括号命令$USER环境变量进行匹配,看它是否以字母r开头。如果是的话,比较通过,shell会执行then部分的命令。

7 case命令

有了case命令,就不需要再写出所有的elif语句来不停地检查同一个变量的值了。case命令会采用列表格式来检查单个变量的多个值。

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

case命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的,那么shell会执行为该模式指定的命令。

可以通过竖线操作符在一行中分隔出多个模式模式。星号会捕获所有与已知模式不匹配的值。

caes $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";;
easc

Welcome, rich
Pleast enjoy your visit

case命令提供了一个更清晰的方法来为变量每个可能的值指定不同的选项。

下一篇我们会继续讨论结构化命令,介绍shell的循环命令,for和while命令。

我们下一篇再见!

相关文章

网友评论

      本文标题:【Linux 基础】五、结构化命令

      本文链接:https://www.haomeiwen.com/subject/aageirtx.html