Chinaunix首页 | 论坛 | 博客
  • 博客访问: 504239
  • 博文数量: 119
  • 博客积分: 5054
  • 博客等级: 大校
  • 技术积分: 1305
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-03 13:13
文章分类

全部博文(119)

文章存档

2011年(4)

2010年(115)

我的朋友

分类:

2010-01-03 22:43:04

摘自《高级bash脚本编程指南》

命令替换能够重新分配一个(对于命令替换来说, 这个命令既可以是外部的系统命令, 也可以是内部脚本的内建命令, 甚至可以是脚本函数. ) 甚至是多个命令的输出; 它会将命令的输出如实地添加到另一个上下文中. (从技术的角度来讲, 命令替换将会抽取一个命令的输出, 然后使用=操作将其赋值到一个变量中. )

命令替换的典型用法形式, 是使用后置引用(`…`). 使用后置引用的(反引号)命令会产生命令行文本.

  1 script_name=`basename $0`
  2 echo "The name of this script is $script_name."

这样一来, 命令的输出就能够保存到变量中, 或者传递到另一个命令中作为这个命令的参数, 甚至可以用来产生for循环的参数列表. .

注:命令替换将会调用一个 subshell.

命令替换可能会引起单词分割(word split).

  1 COMMAND `echo a b`     # 两个参数: a and b
  2
  3 COMMAND "`echo a b`"   # 1个参数: "a b"
  4
  5 COMMAND `echo`         # 无参数
  6
  7 COMMAND "`echo`"       # 一个空参数
  8
  9
 10 # 感谢, S.C.

即使没有引起单词分割(word split), 命令替换也会去掉多余的新行.

如果用echo命令输出一个未引用变量, 而且这个变量以命令替换的结果作为值, 那么这个变量中的换行符将会被删除. 这可能会引起一些异常状况.

  1 dir_listing=`ls -l`
  2 echo $dir_listing     # 未引用, 就是没用引号括起来
  3
  4 # 期望打印出经过排序的目录列表.
  5
  6 # 可惜, 我们只能获得这些:
  7 # total 3 -rw-rw-r-- 1 bozo bozo 30 May 13 17:15 1.txt -rw-rw-r-- 1 bozo
  8 # bozo 51 May 15 20:57 t2.sh -rwxr-xr-x 1 bozo bozo 217 Mar 5 21:13 wi.sh
  9
 10 # 新行消失了.
 11
 12
 13 echo "$dir_listing"   # 引用起来
 14 # -rw-rw-r--    1 bozo       30 May 13 17:15 1.txt
 15 # -rw-rw-r--    1 bozo       51 May 15 20:57 t2.sh
 16 # -rwxr-xr-x    1 bozo      217 Mar  5 21:13 wi.sh

命令替换甚至允许将整个文件的内容放到变量中, 可以使用重定向或者cat命令.

  1 variable1=`

注:不要将一个长文本文件的全部内容设置到变量中, 除非你有一个非常好的原因非这么做不可, 也不要将二进制文件的内容保存到变量中, 即使是开玩笑也不行.

变量替换允许将一个loop的输出设置到一个变量中. 这么做的关键就是将循环中echo命令的输出全部截取.

例子 1. 将一个循环输出的内容设置到变量中

  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上(就像一个标准UNIX工具所做的那样), 然后重新将这些输出保存到变量中. (译者: 作者的意思就是在这种情况下写脚本和写程序作用是一样的.)

  1 #include 
  2
  3 /*  "Hello, world." C program  */
  4
  5 int main()
  6 {
  7   printf( "Hello, world." );
  8   return (0);
  9 }
bash$ gcc -o hello hello.c
  1 #!/bin/bash
  2 # hello.sh
  3
  4 greeting=`./hello`
  5 echo $greeting
bash$ sh hello.sh
Hello, world.

对于命令替换来说, $(COMMAND)形式已经取代了后置引用”`”.

  1 output=$(sed -n /"$1"/p $file)   # 来自于例子"grp.sh".
  2
  3 # 将文本文件的内容保存到一个变量中.
  4 File_contents1=$(cat $file1)
  5 File_contents2=$(<$file2)        # Bash也允许这么做.

$(…)形式的命令替换在处理双反斜线(\\)时与`…`形式不同.

bash$ echo `echo \\`

bash$ echo $(echo \\)
\

$(…)形式的命令替换是允许嵌套的.

word_count=$( wc -w $(ls -l | awk '{print $9}') )

或者, 可以更加灵活 . . .

事实上, 对于后置引用的嵌套是可行的, 但是只能将内部的反引号转义才行.

word_count=` wc -w \`ls -l | awk '{print $9}'\` `

算术扩展

算术扩展提供了一种强力工具, 可以在脚本中执行(整型)算法操作.

一些变化

使用后置引用的算术扩展(通常都是和expr一起使用)

 z=`expr $z + 3`          # 'expr'命令将会执行这个扩展. 

使用双括号形式的算术扩展, 也可以使用let命令

后置引用形式的算术扩展已经被双括号形式所替代了 — ((…))和$((…)) — 当然也可以使用非常方便的let结构.

  1 z=$(($z+3))
  2 z=$((z+3))                                  #  也正确.
  3                                             #  使用双括号的形式,
  4                                             #+ 参数解引用
  5                                             #+ 是可选的.
  6
  7 # $((EXPRESSION))是算数表达式.              #  不要与命令替换
  8                                             #+ 相混淆.
  9
 10
 11
 12 # 使用双括号的形式也可以不用给变量赋值.
 13
 14   n=0
 15   echo "n = $n"                             # n = 0
 16
 17   (( n += 1 ))                              # 递增.
 18 # (( $n += 1 )) is incorrect!
 19   echo "n = $n"                             # n = 1
 20
 21
 22 let z=z+3
 23 let "z += 3"  #  使用引用的形式, 允许在变量赋值的时候存在空格.
 24               #  'let'命令事实上执行得的是算术赋值,
 25               #+ 而不是算术扩展.
阅读(1424) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~