1. 使用多个命令
如果要两个命令一起运行,可以把它们放在同一行中,彼此间用分号隔开。
$ date ; who
Mon Feb 21 15:36:09 EST 2014
Christine tty2 2014-02-21 15:26
Samantha tty3 2014-02-21 15:26
Timothy tty1 2014-02-21 15:26
user tty7 2014-02-19 14:03 (:0)
user pts/0 2014-02-21 15:21 (:0.0)
$
使用这种办法就能将任意多个命令串连在一起使用了,只要不超过最大命令行字符数 255 就行。
2. 创建 shell 脚本文件
在创建 shell 脚本文件时,必须在文件的第一行指定要使用的 shell。其格式为:
#!/bin/bash
在通常的 shell 脚本中,井号(#)用作注释行。shell 并不会处理 shell 脚本中的注释行。然而,shell 脚本文件的第一行是个例外,# 后面的惊叹号会告诉 shell 用哪个 shell 来运行脚本(是的,你可以使用 bash shell,同时还可以使用另一个 shell来运行你的脚本)。
shell 会通过 PATH 环境变量来查找命令。
$ echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin
:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/user/bin
$
PATH 环境变量被设置成只在一组目录中查找命令。要让 shell 找到 test1 脚本,只需采取以下两种作法之一:
- 将shell脚本文件所处的目录添加到PATH环境变量中;
- 在提示符中用绝对或相对文件路径来引用shell脚本文件;
3. 显示消息
在 echo 命令后面加上了一个字符串,该命令就能显示出这个文本字符串
$ echo This is a test
This is a test
$
默认情况下,不需要使用引号将要显示的文本字符串划定出来。
echo 命令可用单引号或双引号来划定文本字符串。如果在字符串中用到了它们,你需要在文本中使用其中一种引号,而用另外一种来将字符串划定起来。
$ echo "This is a test to see if you're paying attention"
This is a test to see if you're paying attention
$ echo 'Rich says "scripting is easy".'
Rich says "scripting is easy".
$
如果想把文本字符串和命令输出显示在同一行中,可以用 echo 语句的 -n 参数
echo -n "The time and date are: $(date)"
4. 使用变量
4.1 环境变量
shell 维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用户名、用户的系统 ID(也称为UID)、用户的默认主目录以及 shell 查找程序的搜索路径。可以用 set 命令来显示一份完整的当前环境变量列表。
$ set
BASH=/bin/bash
[...]
HOME=/home/Samantha
HOSTNAME=localhost.localdomain
HOSTTYPE=i386
IFS=$' \t\n'
IMSETTINGS_INTEGRATE_DESKTOP=yes
IMSETTINGS_MODULE=none
LANG=en_US.utf8
LESSOPEN='|/usr/bin/lesspipe.sh %s'
LINES=24
LOGNAME=Samantha
[...]
在脚本中,你可以在环境变量名称之前加上美元符($)来使用这些环境变量。
$ cat test2
#!/bin/bash
# display user information from the system.
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME
$
# 执行结果如下
$ ./test2
User info for userid: Samantha
UID: 1001
HOME: /home/Samantha
$
注意,echo 命令中的环境变量会在脚本运行时替换成当前值。另外,在第一个字符串中可以将 $USER 系统变量放置到双引号中,而 shell 依然能够知道我们的意图。
要显示美元符,你必须在它前面放置一个反斜线。
$ echo "The cost of the item is \$15"
The cost of the item is $15
4.2 用户变量
用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过 20 个。用户变量区分大小写,所以变量 Var1 和变量 var1 是不同的。
使用等号将值赋给用户变量。在变量、等号和值之间不能出现空格。
shell 脚本会自动决定变量值的数据类型。在脚本的整个生命周期里,shell 脚本中定义的变量会一直保持着它们的值,但在shell 脚本结束时会被删除掉。
$ cat test3
#!/bin/bash
# testing variables
days=10
guest="Katie"
echo "$guest checked in $days days ago"
days=5
guest="Jessica"
echo "$guest checked in $days days ago"
$
运行脚本会有如下输出:
$ chmod u+x test3
$ ./test3
Katie checked in 10 days ago
Jessica checked in 5 days ago
$
变量每次被引用时,都会输出当前赋给它的值。重要的是要记住,引用一个变量值时需要使用美元符,而引用变量来对其进行赋值时则不要使用美元符。
4.3 命令替换
命令替换允许你将 shell 命令的输出赋给变量。有两种方法反引号字符(`)、$() 格式。
- 要么用一对反引号把整个命令行命令围起来:
- 要么使用$()格式:
testing='date'
testing=$(date)
shell 会运行命令替换符号中的命令,并将其输出赋给变量 testing。注意,赋值等号和命令替换字符之间没有空格。
警告 命令替换会创建一个子 shell 来运行对应的命令。子 shell(subshell)是由运行该脚本的 shell所创建出来的一个独立的子shell(child shell)。正因如此,由该子 shell 所执行命令是无法使用脚本中所创建的变量的。在命令行提示符下使用路径./运行命令的话,也会创建出子 shell;要是运行命令的时候不加入路径,就不会创建子 shell。如果你使用的是内建的 shell 命令,并不会涉及子 shell。在命令行提示符下运行脚本时一定要留心!
5. 重定向输入和输出
5.1 输出重定向
最基本的重定向将命令的输出发送到一个文件中。bash shell 用大于号(>)来完成这项功能:
command > outputfile
之前显示器上出现的命令输出会被保存到指定的输出文件中。
$ date > test6
$ ls -l test6
-rw-r--r-- 1 user user 29 Feb 10 17:56 test6
$ cat test6
Thu Feb 10 17:56:58 EDT 2014
$
重定向操作符创建了一个文件 test6(通过默认的 umask 设置),并将 date 命令的输出重定向
到该文件中。如果输出文件已经存在了,重定向操作符会用新的文件数据覆盖已有文件。
$ who > test6
$ cat test6
user pts/0 Feb 10 17:55
$
要将命令的输出追加到已有文件中,可以用双大于号(>>)来追加数据。
5.2 输入重定向
输入重定向和输出重定向正好相反。输入重定向将文件的内容重定向到命令,而非将命令的输出重定向到文件。
输入重定向符号是小于号(<):
command < inputfile
一个简单的记忆方法就是:在命令行上,命令总是在左侧,而重定向符号“指向”数据流动的方向。小于号说明数据正在从输入文件流向命令。
$ wc < test6
2 11 60
$
wc 命令可以对对数据中的文本进行计数,默认情况下,它会输出 3 个值文本的行数、文本的词数、文本的字节数。
内联输入重定向符号是远小于号(<<)。除了这个符号,你必须指定一个文本标记来划分输入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致。
command << marker
data
marker
6. 管道
管道被放在命令之间,将一个命令的输出重定向到另一个命令中:
command1 | command2
不要以为由管道串起的两个命令会依次执行。Linux 系统实际上会同时运行这两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据传输不会用到任何中间文件或缓冲区。
7. 执行数学运算
7.1 expr 命令
expr 命令允许在命令行上处理数学表达式,但是特别笨拙。expr 命令能够识别少数的数学和字符串操作符,一般不推荐使用。
$ expr 1 + 5
6
$ expr 5 * 2
expr: syntax error
$
# 需要使用转义字符反斜线将*号标识出来
$ expr 5 \* 2
10
$
7.2 使用方括号
在将一个数学运算结果赋给某个变量时,可以用美元符和方括号($[ operation ])将数学表达式围起来。该方法比较常用,但仅支持整数运算。
$ var1=$[1 + 5]
$ echo $var1
6
$ var2=$[$var1 * 2]
$ echo $var2
12
$
7.3 浮点解决方案
使用 bc工具
8. 退出脚本
shell 中运行的每个命令都使用退出状态码(exit status)告诉 shell 它已经运行完毕。退出状态码是一个 0~255 的整数值,在命令结束运行时由命令传给 shell。可以捕获这个值并在脚本中使用。
8.1 查看退出状态码
Linux 提供了一个专门的变量 $? 来保存上个已执行命令的退出状态码。对于需要进行检查的
命令,必须在其运行完毕后立刻查看或使用 $? 变量。它的值会变成由 shell 所执行的最后一条命令的退出状态码。
$ date
Sat Jan 15 10:01:30 EDT 2014
$ echo $?
0
$
一个成功结束的命令的退出状态码是 0。
状态码 | 描述 |
---|---|
0 | 命令成功结束 |
1 | 一般性未知错误 |
2 | 不适合的shell命令 |
126 | 命令不可执行 |
127 | 没找到命令 |
128 | 无效的退出参数 |
128+x | 与Linux信号x相关的严重错误 |
130 | 通过Ctrl+C终止的命令 |
255 | 正常范围之外的退出状态码 |
8.2 exit 命令
默认情况下,shell 脚本会以脚本中的最后一个命令的退出状态码退出。
exit 命令允许你在脚本结束时指定一个退出状态码。
$ cat test13
#!/bin/bash
# testing the exit status
var1=10
var2=30
var3=$[$var1 + $var2]
echo The answer is $var3
exit 5
$
当查看脚本的退出码时,你会得到作为参数传给 exit 命令的值。
$ chmod u+x test13
$ ./test13
The answer is 40
$ echo $?
5
$
退出状态码最大只能是 255。