二十三. Bash Shell编程:

  
  1.  读取用户变量:
    read
命令是用于从终端或者文件中读取输入的内建命令,read命令读取整行输入,每行末尾的换行符不被读入。在read命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的变量REPLY。下面的列表给出了read命令的常用方式:

命令格式

描述

read answer

从标准输入读取输入并赋值给变量answer

read first last

从标准输入读取输入到第一个空格或者回车,将输入的第一个单词放到变量first中,并将该行其他的输入放在变量last中。

read

从标准输入读取一行并赋值给特定变量REPLY

read -a arrayname

把单词清单读入arrayname的数组里。

read -p prompt

打印提示,等待输入,并将输入存储在REPLY中。

read -r line

允许输入包含反斜杠。


   
见下面的示例(绿色高亮部分的文本为控制台手工输入信息)
    /> read answer        #等待读取输入,直到回车后表示输入完毕,并将输入赋值给变量answer
    Hello                       #控制台输入Hello
    /> echo $answer      #打印变量
    Hello

    #
等待一组输入,每个单词之间使用空格隔开,直到回车结束,并分别将单词依次赋值给这三个读入变量。
    /> read one two three
    1 2 3                      #在控制台输入1 2 3,它们之间用空格隔开。
    /> echo "one = $one, two = $two, three = $three"
    one = 1, two = 2, three = 3

    /> read                  #等待控制台输入,并将结果赋值给特定内置变量REPLY
    This is REPLY          #在控制台输入该行。
    /> echo $REPLY      #打印输出特定内置变量REPLY,以确认是否被正确赋值。
    This is REPLY

    /> read -p "Enter your name: "    #输出"Enter your name: "文本提示,同时等待输入,并将结果赋值给REPLY
    Enter you name:
 stephen            #在提示文本之后输入stephen
    /> echo $REPLY
    stephen

    #
等待控制台输入,并将输入信息视为数组,赋值给数组变量friends,输入信息用空格隔开数组的每个元素
    /> read -a friends
    Tim Tom Helen
    /> echo "I have ${#friends} friends"
    I have 3 friends
    /> echo "They are ${friends[0]}, ${friends[1]} and ${friends[2]}."
    They are Tim, Tom and Helen.

   2.  状态判断:
    test
Shell中提供的内置命令,主要用于状态的检验,如果结果为0,表示成功,否则表示失败。见如下示例:
    /> name=stephen
    /> test $name != stephen
    /> echo $?
    1
    
需要注意的是test命令不支持Shell中提供的各种通配符,如:
    /> test $name = [Ss]tephen
    /> echo $?
    1
    test
命令还可以中括号予以替换,其语义保持不变,如:
    /> [ $name = stephen ]
    /> echo $?
    0   
 
    
Shell中还提供了另外一种用于状态判断的方式:` expr `,和test不同的是,该方式中的表达式支持通配符,如:
    /> name=stephen
    /> [[ $name == [Ss]tephen ]]
    /> echo $?
    0
    #
` expression `中,expression可以包含&&(逻辑与)||(逻辑或)
    /> [[ $name == [Ss]tephen && $friend == "Jose" ]]
    /> echo $?
    1
    /> shopt -s extglob   #打开Shell的扩展匹配模式。
    /> name=Tommy
    # "[Tt]o+(m)y"
的含义为,以Tt开头,后面跟着一个o,再跟着一个或者多个m,最后以一个y结尾。
    /> [[ $name == [Tt]o+(m)y ]] 
    /> echo $?
    0
    
Shell中还提供了let命令的判断方式: (( expr )),该方式的expr部分,和C语言提供的表达式规则一致,如:
    /> x=2
    /> y=3
    /> (( x > 2 ))
    /> echo $?
    1
    /> (( x < 2 ))
    /> echo $?
    0
  
    /> (( x == 2 && y == 3 ))
    /> echo $?
    0
    /> (( x > 2 || y < 3 ))
    /> echo $?
    1

    下面的表格是test命令支持的操作符:

判断操作符

判断为真的条件

字符串判断

 

[ stringA=stringB ]

stringA等于stringB

[ stringA==stringB ]

stringA等于stringB

[ stringA!=stringB ]

stringA不等于stringB

[ string ]

string不为空

[ -z string ]

string长度为0

[ -n string ]

string长度不为0

逻辑判断

 

[ stringA -a stringB ]

stringAstringB都是真

[ stringA -o stringB ]

stringAstringB是真

[ !string ]

string不为真

逻辑判断(复合判断)

 

[[ pattern1 && pattern2 ]]

pattern1pattern2都是真

[[ pattern1 || pattern2 ]

pattern1pattern2是真

[[ !pattern ]]

pattern不为真

整数判断

 

[ intA -eq intB ]

intA等于intB

[ intA -ne intB ]

intA不等于intB

[ intA -gt intB ]

intA大于intB

[ intA -ge intB ]

intA大于等于intB

[ intA -lt intB ]

intA小于intB

[ intA -le intB ]

intA小于等于intB

文件判断中的二进制操作

 

[ fileA -nt fileB ]

fileAfileB

[ fileA -ot fileB ]

fileAfileB

[ fileA -ef fileB ]

fileAfileB有相同的设备或者inode

文件检验

 

[ -d $file ] or [[ -d $file ]]

file为目录且存在时为真

[ -e $file ] or [[ -e $file ]]

file为文件且存在时为真

[ -f $file ] or [[ -f $file ]]

file为非目录普通文件存在时为真

[ -s $file ] or [[ -s $file ]]

file文件存在, 且长度不为0时为真

[ -L $file ] or [[ -L $file ]]

file为链接符且存在时为真

[ -r $file ] or [[ -r $file ]]

file文件存在且可读时为真

[ -w $file ] or [[ -w $file ]]

file文件存在且可写时为真

[ -x $file ] or [[ -x $file ]]

file文件存在且可执行时为真

    注:在逻辑判断(复合判读中)pattern可以包含元字符,在字符串的判断中,pattern2必须被包含在引号中。

    let
命令支持的操作符和C语言中支持的操作符完全相同,如:
    +,-,*,/,%            加,减,乘,除,去模
    >>,<<                右移和左移
    >=,<=,==,!=      大于等于,小于等于,等于,不等于
    &,|,^                  按位与,或,非
    &&,||,!                逻辑与,逻辑或和取反
    
还有其含义和C语言等同的快捷操作符,如=,*=,/=,%=,+=,-=,<<=,>>=,&=,|=,^=