第五章:引用

引用意味着保护在引号中的字符串. 引用在保护被引起字符串中的特殊字符被shell或shell脚本解释或扩展. (如果一个字符能被特殊解释为不同于它字面上表示的意思,那么这个字符是“特殊”的,比如说通配符 -- *.)

 bash$ ls -l [Vv]*
 -rw-rw-r--    1 bozo  bozo       324 Apr  2 15:05 VIEWDATA.BAT
 -rw-rw-r--    1 bozo  bozo       507 May  4 14:25 vartrace.sh
 -rw-rw-r--    1 bozo  bozo       539 Apr 14 17:11 viewdata.sh
 
 bash$ ls -l '[Vv]*'
 ls: [Vv]*: No such file or directory

某些程序和软件包可以重新解释或扩展引号里的特殊字符。引号一个很重要的作用是保护命令行上的一个参数不被shell解释,而把此参数传递给要执行的程序来处理它。

 bash$ grep '[Ff]irst' *.txt
 file1.txt:This is the first line of file1.txt.
 file2.txt:This is the First line of file2.txt.

注意在Bash shell下如果没有用引号的命令grep [Ff]irst *.txt会怎么样。[1]

引号也能改掉echo's不换行的“习惯”。

 bash$ echo $(ls -l)
 total 8 -rw-rw-r-- 1 bozo bozo 130 Aug 21 12:57 t222.sh -rw-rw-r-- 1 bozo bozo 78 Aug 21 12:57 t71.sh
 
 
 bash$ echo "$(ls -l)"
 total 8
 -rw-rw-r--  1 bozo bozo 130 Aug 21 12:57 t222.sh
 -rw-rw-r--  1 bozo bozo  78 Aug 21 12:57 t71.sh

5.1. 引用变量

当要引用一个变量的值时,一般推荐使用双引号。使用双引号除了变量名[2]前缀($)、后引符(`)和转义符(\)外,会使shell不再解释引号中其它所有的特殊字符。[3] 用双引号时$仍被当成特殊字符,允许引用一个被双引号引起的变量("$variable"), 那也是说$variable会被它的值所代替。(参考上面的例子 4-1).

用双引号还能使句子不被分割开. [4] 一个参数用双引号引起来能使它被看做一个单元,这样即使参数里面包含有空白字符也不会被shell分割开了。
   1 variable1="a variable containing five words"
   2 COMMAND This is $variable1    # 用下面7个参数执行COMMAND命令:
   3 # "This" "is" "a" "variable" "containing" "five" "words"
   4 
   5 COMMAND "This is $variable1"  # 用下面1个参数执行COMMAND命令:
   6 # "This is a variable containing five words"
   7 
   8 
   9 variable2=""    # 空字符串。
  10 
  11 COMMAND $variable2 $variable2 $variable2        # 没有带参数执行COMMAND 命令
  12 COMMAND "$variable2" "$variable2" "$variable2"  # 用三个含空字符串的参数执行COMMAND命令
  13 COMMAND "$variable2 $variable2 $variable2"      # 用一个包含两个空白符的参数执行COMMAND命令
  14 
  15 # Thanks, St閜hane Chazelas.

Tip

在echo语句中,只有句子分割和保存空白符的时候,才需要把参数用双引号引起来。.


例子 5-1. 引号引起奇怪的变量

   1 #!/bin/bash
   2 # weirdvars.sh: Echoing weird variables.
   3 
   4 var="'(]\\{}\$\""
   5 echo $var        # '(]\{}$"
   6 echo "$var"      # '(]\{}$"     和上面一句没什么不同.
   7 
   8 echo
   9 
  10 IFS='\'
  11 echo $var        # '(] {}$"     \字符被空白符替换了,为什么?
  12 echo "$var"      # '(]\{}$"
  13 
  14 # 以上例子由Stephane Chazelas提供..
  15 
  16 exit 0

单引号(' ')和双引号类似,但它不允许解释变量引用,因此,在单引号内的字符$的特殊意思无效了。在单引号内,除了字符',每个特殊字符都只是字面的意思。单引号(全局引用)比双引号(部分引用)更严格的处理引用部分。

Note

由于在单引号里的转义字符(\)也只是被局限于字面上的意思,所以想在一双单引号里再加单引号是不行的。
   1 echo "Why can't I write 's between single quotes"
   2 
   3 echo
   4 
   5 # The roundabout method.
   6 echo 'Why can'\''t I write '"'"'s between single quotes'
   7 #    |-------|  |----------|   |-----------------------|
   8 # 三个单引号引起的字符串之间有一个转义的单引号和一个由双引号引起的单引号.
   9 
  10 # 这个例子得到 St閜hane Chazelas同意.

注:

[1]

除非当前目录下有一个文件名为first的文件。那这是引用的另外一个不同的理由了。(多谢 Harald Koenig指出这一点)

[2]

这也会使变量的值会有副作用。(看下面的)

[3]

在命令行上,把感叹号"!"放在双引号里执行命令会出错(译者注:比如说:echo "hello!"). 因为感叹号被解释成了一个历史命令. 然而在一个脚本文件里,这么写则是正确的,因为在脚本文件里Bash的历史机制被禁用了。

在双号号里在字符"\"也会引起许多不一致的行为。
 bash$ echo hello\!
 hello!
 
 
 bash$ echo "hello\!"
 hello\!
 
 
 
 
 bash$ echo -e x\ty
 xty
 
 
 bash$ echo -e "x\ty"
 x       y
 	      
(多谢Wayne Pollock指出这一点)

[4]

句子的分割,在这里是指分割一个字符串为许多不连续的单独的参数。