文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>高级shell编程技巧5(转载)

高级shell编程技巧5(转载)

时间:2006-06-02  来源:lin_lin13

<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"><title></title><meta name="GENERATOR" content="OpenOffice.org 2.0 (Linux)"><meta name="AUTHOR" content="lin lin"><meta name="CREATED" content="20060525;8284000"><meta name="CHANGEDBY" content="lin lin"><meta name="CHANGED" content="20060525;8323700"> <style> </style>

第5章 引用(翻译的可能有问题,特指引号)

======================================

引号的特殊效果就是,保护字符串中的特殊字符不被shell或者是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


在我们一般的生活中,引号内的内容往往有特殊的含义,而在Bash中,当我们引用一个字符串,

我们是保护它的字面含义.


特定的程序和工具能够重新解释或扩展特殊的字符.引用的一个重要的作用就是保护命令行中

的参数,但还是允许正在调用的程序来扩展它.

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.


注意 grep [Ff]irst *.txt在Bash下的行为(其实就是正则表达式么),[1]


引用还可以抑制echo命令的换行作用.


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]--但是$,`和\除外.[3]保留$,作为特殊字符的意义,是为了能够在双

引号中也能够正常地引用变量("$var").这样在""中可以使用变量所表达的值(Example 4-1).


使用""来防止单词分割.[4]如果在参数列表中使用双引号,将使得双引号中的参数作为一个参

数.即使双引号中的字符串包含多个单词(也就是包含空白部分),也不会变为多个参数,如:

1 variable1="a variable containing five words"

2 COMMAND This is $variable1 # COMMAND将以7个参数来执行

3 # "This" "is" "a" "variable" "containing" "five" "words"

4

5 COMMAND "This is $variable1" # COMMAND将以1个参数来执行

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将以3个空参数来执行

13 COMMAND "$variable2 $variable2 $variable2" # COMMAND将以1个参数来执行(2空格)

用双引号把参数封到echo中是很有必要的,只有在单词分隔或时保留空白时的时候可能

有些问题.


Example 5-1 echo一些诡异的变量

################################Start Script#######################################

1 #!/bin/bash

2 # weirdvars.sh: echo诡异的变量

3

4 var="'(]\\{}\$\""

5 echo $var # '(]\{}$"

6 echo "$var" # '(]\{}$" 并没有什么不同

7

8 echo

9

10 IFS='\'

11 echo $var # '(] {}$" \ 转换成空格了?明显和IFS有关系么!又不傻!

12 echo "$var" # '(]\{}$"

13

14 exit 0

################################End Script#########################################


单引号操作总体上和""很像,但不允许引用变量.因为$的特殊含义被关闭了.在''中除了',其他

字符都没有特殊的含义了.所以单引号比双引号严格.

因为即使是\,在''中都被关闭了,所以你想在''中显示'的含义,将得不到预期的效果.

1 echo "Why can't I write 's between single quotes"

2

3 echo

4

5 # 一种绕弯的方法

6 echo 'Why can'\''t I write '"'"'s between single quotes'

7 # |-------| |----------| |-----------------------|

8 # 包含了2个单引号字符,原书好像有错误


注意事项:

[1] 除非当前目录下,正好有个叫first的文件.

[2] 即使是变量的值也是有副作用的(见下边)

[3] 如果在""中包含"!"的话,在命令行中将会出现错误.因为这个"!"被当作历史命令来解释了.

在一个脚本中,这种情况是不会发生的,因为在脚本中,Bash历史记录被关闭了.


下边是一些关于"\"一些不协调的行为.

bash$ echo hello\!

hello!


bash$ echo "hello\!"

hello\!


bash$ echo -e x\ty

xty


bash$ echo -e "x\ty"

x y


[4] "单词分隔",在这个上下文中意味着,将一个字符串分隔为一些分离的参数.



5.2 转义(\)

-----------

转义是一种引用单个字符的方法.一个具有特殊含义的字符前边放上一个转义符(\)就告诉shell

这个字符失去了特殊的含义.

值得注意的是,在某些特定的命令和工具中,比如echo和sed,转义符往往会起到相反的效果,

它反倒有可能引发出这个字符特殊的含义.


对于特定的转义符的特殊的含义

在echo和sed中所使用的

\n 意味着新的一行

\r 回车

\t tab键

\v vertical tab(垂直tab),查前边的Ctl-K

\b backspace,查前边的Ctl-H

\a "alert"(如beep或flash)

\0xx 转换成8进制ASCII解码,等价于oxx


Example 5-2 转义符

################################Start Script#######################################

1 #!/bin/bash

2 # escaped.sh: 转义符

3

4 echo; echo

5

6 echo "\v\v\v\v" # 逐字的打印\v\v\v\v .

7 # 使用-e选项的echo命令来打印转义符

8 echo "============="

9 echo "VERTICAL TABS"

10 echo -e "\v\v\v\v" # Prints 4 vertical tabs.

11 echo "=============="

12

13 echo "QUOTATION MARK"

14 echo -e "\042" # 打印" (引号, 8进制的ASCII 码就是42).

15 echo "=============="

16

17 # The $'\X' construct makes the -e option unnecessary.

17 # 如果使用$'\X'结构,那-e选项就不必要了

18 echo; echo "NEWLINE AND BEEP"

19 echo $'\n' # 新行.

20 echo $'\a' # Alert (beep).

21

22 echo "==============="

23 echo "QUOTATION MARKS"

24 # 版本2以后Bash允许使用$'\nnn'结构

25 # 注意这种情况,'\nnn\是8进制

26 echo $'\t \042 \t' # Quote (") framed by tabs.

27

28 # 当然,也可以使用16进制的值,使用$'\xhhh' 结构

29 echo $'\t \x22 \t' # Quote (") framed by tabs.

30

31 # 早一点的Bash版本允许'\x022'这种形式

32 echo "==============="

33 echo

34

35

36 # 分配ASCII字符到变量中

37 # ---------------------

38 quote=$'\042' # \042是",分配到变量中

39 echo "$quote This is a quoted string, $quote and this lies outside the quotes."

40

41 echo

42

43 # Concatenating ASCII chars in a variable.

43 # 变量中的连续的ASCII char.

44 triple_underline=$'\137\137\137' # 137 是8进制的ASCII 码'_'.

45 echo "$triple_underline UNDERLINE $triple_underline"

46

47 echo

48

49 ABC=$'\101\102\103\010' # 101, 102, 103 是8进制的码A, B, C.

50 echo $ABC

51

52 echo; echo

53

54 escape=$'\033' # 033 是8进制码for escape.

55 echo "\"escape\" echoes as $escape"

56 #"escape" echoes as 没有变量被输出

57

58 echo; echo

59

60 exit 0

################################End Script#########################################

另一个关于$''字符串扩展结果的例子见Example 34-1


\" 表达引号本身

1 echo "Hello" # Hello

2 echo "\"Hello\", he said." # "Hello", he said.


\$ $号本身,跟在\$后的变量名,将不能扩展

1 echo "\$variable01" # 结果是$variable01


\\ \号本身.

1 echo "\\" # 结果是\

2

3 # 相反的 . . .

4

5 echo "\" # 这会出现第2个命令提示符,说白了就是提示你命令不全,你再补个"就

6 # 好了.如果是在脚本里,就会给出一个错误.


注意:\的行为依赖于它是否被转义,被"",或者是否在"命令替换"和"here document"中.

################################Start Script#######################################

1 # 简单的转义和""

2 echo \z # z

3 echo \\z # \z

4 echo '\z' # \z

5 echo '\\z' # \\z

6 echo "\z" # \z

7 echo "\\z" # \z

8

9 # 命令替换

10 echo `echo \z` # z

11 echo `echo \\z` # z

12 echo `echo \\\z` # \z

13 echo `echo \\\\z` # \z

14 echo `echo \\\\\\z` # \z

15 echo `echo \\\\\\\z` # \\z

16 echo `echo "\z"` # \z

17 echo `echo "\\z"` # \z

18

19 # Here document

20 cat <<EOF

21 \z

22 EOF # \z

23

24 cat <<EOF

25 \\z

26 EOF # \z

################################End Script#########################################


分配给变量的字符串的元素也会被转义,但是只把一个转义符分配给变量将会报错.

################################Start Script#######################################

1 variable=\

2 echo "$variable"

3 # Will not work - gives an error message:

3 # 将不能正常工作- 将给出一个错误消息:

4 # test.sh: : command not found

5 # 一个"裸体的" 转义符将不能够安全的分配给变量.

6 #

7 # What actually happens here is that the "\" escapes the newline and

7 # 这里其实真正发生的是variable=\,这句被shell认为是没有完成,\被认为是一个续行符

8 #+ 这样,下边的这句echo,也被认为是上一行的补充.所以,总的来说就是一个非法变量分配

9

10 variable=\

11 23skidoo

12 echo "$variable" # 23skidoo

13 # 这句就可以使用,因为这是一个合法的变量分配

14

15 variable=\

16 # \^ 转义一个空格

17 echo "$variable" # 显示空格

18

19 variable=\\

20 echo "$variable" # \

21

22 variable=\\\

23 echo "$variable"

24 # 不能正常工作,给出一个错误

25 # test.sh: \: command not found

26 #

27 # 第一个转义符把第2个\转义了,但是第3个又变成"裸体的"了,

28 #+ 与上边的例子的原因相同

29

30 variable=\\\\

31 echo "$variable" # \\

32 # 转了两个\

33 # 没问题

################################End Script#########################################


转义一个空格,在命令行参数列表中将会阻止单词分隔问题.

################################Start Script#######################################

1 file_list="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7"

2 # 列出的文件都作为命令的参数.

3

4 # Add two files to the list, and list all.

4 # 加2个文件到list中,并且列出全部.

5 ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list

6

7 echo "-------------------------------------------------------------------------"

8

9 # 如果我们转义2个空格,会发生什么?

10 ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list

11 # 错误: 因为前3个路径名被合并成一个参数传给了'ls -l'

12 # 因为2个转义符阻止了参数(单词)分离

################################End Script#########################################


转义符也提供续行功能.一般,每一行都包含一个不同的命令,但如果在行尾加上\,那就会接受

新行的输入,作为这一行的补充.

1 (cd /source/directory && tar cf - . ) | \

2 (cd /dest/directory && tar xpvf -)

3 # 重复了 Alan Cox的目录树拷贝命令

4 # 为了增加可读性分成2行.

5

6 # 也可以使用如下方式:

7 tar cf - -C /source/directory . |

8 tar xpvf - -C /dest/directory

9 # 察看下边的注意事项


注意:如果一个脚本以|(管道字符)结束.那么一个\(转义符),就不用非加上不可了.

但是一个好的shell脚本编写风格,还是应该在行尾加上\,以增加可读性.

################################Start Script#######################################

1 echo "foo

2 bar"

3 #foo

4 #bar

5

6 echo

7

8 echo 'foo

9 bar' # 没区别

10 #foo

11 #bar

12

13 echo

14

15 echo foo\

16 bar # 续行

17 #foobar

18

19 echo

20

21 echo "foo\

22 bar" # 与上边一样,\还是作为续行符

23 #foobar

24

25 echo

26

27 echo 'foo\

28 bar' # 由于是强引用,所以\没被解释成续行符

29 #foo\

30 #bar

################################End Script#########################################



相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载