命令替换 将会重新分配一个命令[1]甚至是多个命令的输出; 它会将命令的输出如实地添加到另一个上下文中. [2]
使用命令替换的典型形式是使用后置引用(`...`). 后置引用形式的命令(就是被反引号括起来)将会产生命令行文本.
1 script_name=`basename $0` 2 echo "The name of this script is $script_name." |
这样的话, 命令的输出可以被当成传递到另一个命令的参数, 或者保存到变量中, 甚至可以用来产生for循环的参数列表.
1 rm `cat filename` # "filename" 包含了需要被删除的文件列表.
2 #
3 # S. C. 指出使用这种形式, 可能会产生"参数列表太长"的错误.
4 # 更好的方法是 xargs rm -- < filename
5 # ( -- 同时覆盖了那些以"-"开头的文件所产生的特殊情况 )
6
7 textfile_listing=`ls *.txt`
8 # 变量中包含了当前工作目录下所有的*.txt文件.
9 echo $textfile_listing
10
11 textfile_listing2=$(ls *.txt) # 这是命令替换的另一种形式.
12 echo $textfile_listing2
13 # 同样的结果.
14
15 # 将文件列表放入到一个字符串中的一个可能的问题就是
16 # 可能会混进一个新行.
17 #
18 # 一个安全的将文件列表传递到参数中的方法就是使用数组.
19 # shopt -s nullglob # 如果不匹配, 那就不进行文件名扩展.
20 # textfile_listing=( *.txt )
21 #
22 # Thanks, S.C. |
命令替换将会调用一个subshell. |
命令替换可能会引起word splitting.
即使没有引起word splitting, 命令替换也会去掉多余的新行.
|
当一个变量是使用命令替换的结果做为值的时候, 然后使用echo命令来输出这个变量(并且不引用这个变量, 就是不用引号括起来), 那么命令替换将会从最终的输出中删掉换行符. 这可能会引起一些异常情况.
|
命令替换甚至允许将整个文件的内容放到变量中, 可以使用重定向或者cat命令.
1 variable1=`<file1` # 将"file1"的内容放到"variable1"中. 2 variable2=`cat file2` # 将"file2"的内容放到"variable2"中. 3 # 但是这行将会fork一个新进程, This, however, forks a new process, 4 #+ 所以这行代码将会比第一行代码执行得慢. 5 6 # 注意: 7 # 变量中是可以包含空白的, 8 #+ 甚至是 (厌恶至极的), 控制字符. |
1 # 摘录自系统文件, /etc/rc.d/rc.sysinit 2 #+ (这是红帽安装中使用的) 3 4 5 if [ -f /fsckoptions ]; then 6 fsckoptions=`cat /fsckoptions` 7 ... 8 fi 9 # 10 # 11 if [ -e "/proc/ide/${disk[$device]}/media" ] ; then 12 hdmedia=`cat /proc/ide/${disk[$device]}/media` 13 ... 14 fi 15 # 16 # 17 if [ ! -n "`uname -r | grep -- "-"`" ]; then 18 ktag="`cat /proc/version`" 19 ... 20 fi 21 # 22 # 23 if [ $usb = "1" ]; then 24 sleep 5 25 mouseoutput=`cat /proc/bus/usb/devices 2>/dev/null|grep -E "^I.*Cls=03.*Prot=02"` 26 kbdoutput=`cat /proc/bus/usb/devices 2>/dev/null|grep -E "^I.*Cls=03.*Prot=01"` 27 ... 28 fi |
变量替换允许将一个循环的输出放入到一个变量中.这么做的关键就是将循环中echo命令的输出全部截取.
Example 14-2. 从循环的输出中产生一个变量
1 #!/bin/bash 2 # csubloop.sh: 从循环的输出中产生一个变量. 3 4 variable1=`for i in 1 2 3 4 5 5 do 6 echo -n "$i" # 对于这里的命令替换来说 7 done` #+ 这个'echo'命令是非常关键的. 8 9 echo "variable1 = $variable1" # variable1 = 12345 10 11 12 i=0 13 variable2=`while [ "$i" -lt 10 ] 14 do 15 echo -n "$i" # 再来一个, 'echo'是必须的. 16 let "i += 1" # 递增. 17 done` 18 19 echo "variable2 = $variable2" # variable2 = 0123456789 20 21 # 这就证明了在一个变量声明中 22 #+ 嵌入一个循环是可行的. 23 24 exit 0 |
命令替换使得扩展有效的Bash工具集变为可能. 这样, 写一段小程序或者一段脚本就可以达到目的, 因为程序或脚本的输出会传到stdout上(就像一个标准的工具所做的那样), 然后重新将这些输出保存到变量中.(译者: 作者的意思就是在这种情况下写脚本和写程序作用是一样的.)
|
对于命令替换来说,$(COMMAND) 形式已经取代了反引号"`".
$(...) 形式的命令替换在处理双反斜线(\\)时与`...`形式不同.
$(...) 形式的命令替换是允许嵌套的. [3]
或者, 可以更加灵活. . . Example 14-3. 找anagram(回文构词法, 可以将一个有意义的单词, 变换为1个或多个有意义的单词, 但是还是原来的子母集合)
|
命令替换在脚本中使用的例子:
[1] | 对于命令替换来说, 这个命令可以是外部的系统命令, 也可以是内部脚本的内建命令, 甚至是一个脚本函数. | |
[2] | 从技术的角度来讲, 命令替换将会抽取出一个命令的输出, 然后使用=操作赋值到一个变量中. | |
[3] | 事实上, 对于反引号的嵌套是可行的, 但是只能将内部的反引号转义才行, 就像John默认指出的那样.
|