8.命令列表
有时,我们想要将几条命令连接成一个序列。例如,我们可能想在执行某个语句之前满足好几个不同的条件,shell提供了一对特殊的结构,专门用于处理命令列表,他们分别是:AND列表和OR列表。虽然它们通常在一起使用,但我们将分别介绍它们的语法。
AND 列表
AND列表结构允许我们按照这样的方式执行一系列命令:只有在前面所有命令都执行成功的情况下才执行后一条命令。
它的语法是:
statement1 && statement2 && statement3 && ....
从左开始顺序执行每条命令,如果一条命令返回是true,它右边的下一条命令才能够执行。如此循环直到有一条命令返回false,或者列表中的所有命令都执行完毕。&&的作用是检查前一条命令的返回值。
如果AND列表中的所有命令都执行成功,就算它执行成功,否则就算它失败。
实验:AND列表
#!/bin/sh
touch file_one
rm -f file_two
if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo "there"
then
echo -e "in if"
else
echo -e "in else"
fi
exit 0
实验解析:
touch 创建了文件file_one ,rm 删除了文件 file_two ,所以&&列表执行[ -f file_one ] 语句执行成功,所以执行下一条命令echo "hello" ,这个命令也执行成功,(因为echo命令总是返回true)。当执行第三个测试命令[ -f file_two ] ,因为该文件已被删除所以执行结果为flase, if语句将执行else 部分语句。
OR列表
OR列表结构允许我们持续执行一系列命令直到有一条命令成功为止,其后的命令将不再被执行。
它的语法是:
statement1|| statement2 || statement3|| ....
从左开始顺序执行每条命令。如果一条命令返回是false,它的右边的下一条命令才能够被执行。如此循环直到有一条命令返回true,或者列表中的所有命令都执行完毕。
实验:OR列表
#!/bin/sh
rm -f file_one
if [ -f file_one ] || echo "hello" || echo "there"
then
echo "in if"
else
echo "in else"
fi
exit 0
实验解析:
||的第一条语句返回是flase,继续执行下一条语句,echo "hello" 语句返回的是true, 所以直接执行then 部分
结果打印信息:
hello
in if
来看下面例子,就是对AND 和 OR最好的解析
例s5:
#!/bin/sh
Folder=/home
[-r “$folder”]&& echo “can read $folder” (&&前的条件为真时才执行&&后的语句)
[-f “$folder”] || echo “this is not file”(||前的条件为假时才执行||后的语句)
结果打印信息:
can read /home
this is not file
总结: |
| | :直到遇到真(返回true)才不执行 |
&&:直到遇到假(返回flase)才不执行 |
<四>命令
1.eval命令
eval命令允许你对参数进行求值。它是shell的内置命令,通常不会以单独命令的形式存在。我们可以借用X/Open规范中的一个小例子来演示它的用法。
foo=10
x=foo
y=‘$' $x
echo $y
它输出“$foo”而
foo=10
x=foo
eval y='$'$x
echo $y
输出 10.因此,eval命令有点像一个额外的$,它给出一个变量的值的值。
2.exit n 命令
在shell脚本编程中,退出码0表示成功,退出码1~125是脚本程序使用的错误代码。其余数字具有保留含义。
退出码 | 说明 |
126 127 128以上 | 文件不可执行 命令未找到 出现信号 |
3. export 命令
export命令将作为它参数的变量导出到子shell中,并使之在子shell中有效。默认情况下,在一个shell中被创建的变量在这个shell调用的下级(子)shell中是不可用的。export命令把自己的参数创建为一个环境变量,而这个环境变量可以被其他脚本和当前程序调用的程序看见。从更技术的角度说,被导出的变量构成从该shell衍生的任何子进程的环境变量。我们用下面两个脚本程序export1 和export2来说明。
实验:导出变量
(1)我们先列出脚本程序export2:
#!/bin/sh
echo "$foo"
echo "$bar"
(2)下面是脚本程序export1.在这个脚本的结尾,我们调用export2:
#!/bin/sh
foo="The first meta-syntactic variable"
export bar="The second meta-syntactic variable"
./export2
运行export1这个脚本程序,将得到如下输出:
The second meta-syntactic variable
第一个空行的出现是因为变量foo在export2中不可用,所以$foo被赋值为空,echo一个空变量将输出一个空行。
当变量被一个shell导出后,它就可以被该shell调用的任何脚本使用,也可被后续调用的任何shell使用。如果脚本export2调用了另一个脚本,bar的值对新脚本来说任然有效。
set -a 或 set -all export命令将导出它之后声明的所有变量 |
4.expr 命令
expr命令将它的参数当做一个表达式来求值。它的最常见的用法是进行如下的简答数学运算:
方法一: x=`expr $x+1`
反引号(` `)字符使x取值为命令expr$x+1的执行结果。我们也可以用语法$()替换反引号``,如下所示:
方法二:x=$(expr $x+1)
在最新的脚本程序中,expr命令被替换为更有效的$((...))语法,这个我们在后面提到。
5. set 命令
set 命令的作用是为shell设置参数变量。许多命令的输出结果是以空格分隔的值(域),如果需要使用输出结果中的某个域,这个命令就非常有用。
我们来看下面这个例子就容易明白了:
#!/bin/sh
echo The date is $(date)
set $(date)
echo The month is $2
exit 0
输出结果:
实验解析:
系统本身提供了一个data命令,它的输出时字符串形式的 年 月 日 星期 ... ,但是我们需要的是 月份这就需要将它与其他区域分隔开,我们使用set命令和$(...)结构的组合来date 的输出结果设置为参数列表,然后通过位置参数$2获得月份。 月份字符串是 date 命令输出结果的 第二个参数。
6.find命令
find命令的完整语法格式如下:
fine [path] [options] [test ] [actions]
实验:使用测试的find命令
当前目录下搜索比文件while2要新的文件
命令: find . -newer while2 -print
.
./elif3
./words.txt
./words2.txt
./_trap
这个结果看起来不错,不过结果中还包含了当前目录,而这个并不是我们想要的,我们只对普通文件感兴趣。所以我们需要增加一个额外的测试 -type f
./elif3
./words.txt
./words2.txt
./_trap
7.grep命令
grep命令时在文件中搜索字符串 | find命令时在系统中搜索文件 |
<五>命令执行
编写脚本程序时,我们经常需要捕获一条命令的执行结果并把它用在shell脚本程序中,也就是说,我们想要执行一条命令并把该命令的输出到一个变量中。我们可以用前面set命令示例中介绍的$(command) 语法来实现,也可以用一种比较老的语法形式`command`,这种用法目前依然常见。
注意:在脚本程序里执行比较老的语法形式所使用的的反引号 ` ,而不是我们前面使用的单引号 ' (单引号是防止变量扩展) |
所有的新脚本的程序都应该使用$(...)形式,引入这一形式的目的是避免在使用反引号时过于复杂。
$(command)的结果就是其中命令的输出。注意这不是该命令的退出状态,而是他的字符串形式的输出结果。例如:
#! /bin/sh
echo the current directory is $pwd
echo the currentuser is $(who)
exit 0
1.算术扩展
我们已经介绍过expr命令,它允许对简单的算术命令进行处理,但这个命令执行起来相当慢,因为它需要调用一条新的shell来处理expr命令,一种更好的办法就是使用$((...))扩展,如下:
#! /bin/sh
x=0
while [ "$x" -ne 10 ] ;do
echo $x
x=$(($x+1))
done
exit 0
注意:这与x=$(...)命令不同,两对圆括号用于算术替换,而我们之前见到的一对圆括号用于命令的执行和获取输出 |
2.参数扩展
注意:有时候变量名很容易与其他文字混淆,比如:
S13:
Num=2
Echo “this is the $numnd”
思考:输出?why?
答案:num=2
Echo “this is the $numnd”
这并不会打印出““this is the2nd”,而仅仅打印“this is the”,因为shell会去搜索变量numnd的值,但是这个变量是没有的。可以使用花括号来告诉shell我们要打印的是num变量:
Num=2
Echo “this is the ${num}nd”
这将打印:this is the 2nd