shell脚本的关键在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给另一个命令。
shell可以让你将多个命令串起来,一次执行完成。如果要两个命令一起运行,可以把它们放在同一行中,彼此间用分号隔开。
在创建shell脚本文件时,必须在文件的第一行指定要使用的shell。其格式为:
#!/bin/bash
shell会按根据命令在文件中出现的顺序进行处理。
ps:脚本注释以#
表示(除了以#!
开头的第一行)。
一般情况下在echo命令后面跟着字符串就可以在终端将字符串消息显示出来了。
eg:
echo my name is george. -> my name is george
Q:如何在显示消息中带上单/双引号?
A:echo命令可用单引号或双引号来划定文本字符串。
echo 'my name is "george".' -> my name is "george".
echo "my name is 'george'." -> my name is 'george'.
Q:如何把文本字符串和命令输出显示在同一行中?
A:使用echo -n
参数。
echo -n "date is "
date -> date is 2020年 03月 02日 星期一 15:03:14 CST (这里date命令需要换行或者使用分号隔开)
eg:echo -n "date is " ;date
变量允许临时性地将信息存储在shell脚本中,以便和脚本中的其他命令一起使用。
shell维护着一组环境变量,用来记录特定的系统信息。
set命令来显示一份完整的当前环境变量列表。
在脚本中,可以在环境变量名称之前加上美元符($)来使用这些环境变量。
ps:要显示美元符,你必须在它前面放置一个反斜线
eg:echo "The cost of the item is \$15"
notice:你可能还见过通过${variable}形式引用的变量。变量名两侧额外的花括号通常用来帮助识别美元符后的变量名。
用户变量自身以及使用有如下特点:
eg:
shell脚本会自动决定变量值的数据类型。
用户变量的生命周期和脚本同等。即脚本结束用户变量生命周期也到。
ps:用户变量可通过美元符引用,没有美元符,shell会将变量名解释成普通的文本字符串。
shell脚本中最有用的特性之一就是可以从命令输出中提取信息,并将其赋给变量。
有如下两种方式实现命令替换:
eg:
#mydate=`date`
mydate=$(date)
echo $mydate
-> 2020年 03月 02日 星期一 16:23:49 CST
notice:
命令替换会创建一个子shell来运行对应的命令。子shell(subshell)是由运行该脚本的shell所创建出来的一个独立的子shell(child shell)。正因如此,由该子shell所执行命令是无法使用脚本中所创建的变量的。
在命令行提示符下使用路径./运行命令的话,也会创建出子shell;要是运行命令的时候不加入路径,就不会创建子shell。
如果你使用的是内建的shell命令,并不会涉及子shell。在命令行提示符下运行脚本时一定要留心!
最基本的重定向将命令的输出发送到一个文件中。
eg:
ls > ls.txt
ls -la >> ls.txt
输入重定向将文件的内容重定向到命令,而非将命令的输出重定向到文件。
Q:如何方便对统计数据文本计数?
A:使用<
符号和wc
命令。
eg:wc < 1.txt
wc命令可以对对数据中的文本进行计数。默认情况下会输出三个值:
另外还有一种输入重定向的方法称为内联输入重定向(inline input redirection)。
符号采用<<
。
除了这个符号,你必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致。
在命令行上使用内联输入重定向时,shell会用PS2环境变量中定义的次提示符来提示输入数据。
eg:
wc << a
>1
>2
>a
2 2 4
上述>
就是次提示符。次提示符会持续提示,以获取更多的输入数据,直到你输入了作为文本标记的那个字符串。wc命令会对内联输入重定向提供的数据进行行、词和字节计数。
管道连接(piping):可以将命令输出直接重定向到另一个命令。
eg:
ls | more
notice:
不要以为由管道串起的两个命令会依次执行。Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据传输不会用到任何中间文件或缓冲区。
expr命令允许在命令行上处理数学表达式,但是特别笨拙。
expr命令能够识别少数的数学和字符串操作符。如下图所示:
要将一个数学算式的结果赋给一个变量,需要使用命令替换来获取expr命令的输出。
eg:
#!/bin/bash
# An example of using the expr command
var1=10
var2=20
var3=$(expr $var2 / $var1) //使用命令替换来获取expr命令的输出
echo The result is $var3
许多expr命令操作符在shell中另有含义(比如星号)。当它们出现在在expr命令中时,会得到一些诡异的结果。
eg:
expr 20 * 10 -> expr: 语法错误 (因为*在命令行中有通配符的意义)
解决方法:使用转义字符(反斜杠\)
expr 20 \* 10 -> 200
在bash中,在将一个数学运算结果赋给某个变量时,可以用美元符和方括号($[ operation ])将数学表达式围起来。
eg:
var1=100
var2=5
echo $[var1 * var2] -> 500
ps:因为有方括号的存在,不用担心shell会误解乘号或者其他符号。
notice:
为了解决bash中数学运算的整数限制。最常见的解决办法是使用内建的bash计算器,称为bc。
Q:bc如何使用?
A:bash计算器实际上是一种编程语言,它允许在命令行中输入浮点表达式,然后解释并计算该
表达式,最后返回结果。bash计算器能够识别:
Q:脚本中如何使用bc?
A:可以用命令替换运行bc命令,并将输出赋给一个变量。基本格式如下:
variable=$(echo "options; expression" | bc)
notice:浮点运算是由内建变量scale控制的。必须将这个值设置为你希望在计算结果中保留的小数
位数,否则无法得到期望的结果。
eg:
echo $(echo "var3=4; 3.44 / 5" | bc) -> 0
echo $(echo "scale=4; 3.44 / 5" | bc) -> 0.6880 //注意scale的值。
var3 和 scale 的赋值效果只在bc计算器中有效。
注意:在bash计算器(bc计算器)中创建的变量只在bash计算器中有效,不能在shell脚本中使用。
通常情况下,运行完最后一条命令时,脚本就结束了。
shell中运行的每个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用。
$?
Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。
它的值会变成由shell所执行的最后一条命令的退出状态码。
eg:
echo $?
0 //0即是最后一条命令的退出状态码
按照惯例,一个成功结束的命令的退出状态码是0。如果一个命令结束时有错误,退出状态码就是一个正数值。
eg:
a
echo $?
127 //因为没有a这个命令。产生错误状态码
Linux错误退出状态码没有什么标准可循,但有一些可用的参考。如下图所示:
默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。
Q:什么是非默认情况?
A:非默认情况就是退出状态码不是随脚本中的最后一个命令的状态码变化。
exit命令允许在脚本结束时指定一个退出状态码。
ps:exit命令指定的退出状态码最大只能是255。
eg:
var3=1
echo $var3
exit 5
echo $?
5
申明:文中没特殊注明,图皆来自Linux命令行与shell脚本编程大全<第三版>。