- 论坛徽章:
- 0
|
here document 就是一段特殊目的的代码块. 他使用
I/O 重定向
的形式来将一个命令序列传递到一个交互程序或者命令中, 比如
ftp
,
cat
, 或者ex文本编辑器.
1 COMMAND
limit string 用来划定命令序列的范围(译者注: 两个相同的limit string之间就是命令序列). 特殊符号 用来表识limit string. 这个符号具有重定向文件的输出到程序或命令的输入的作用. 与 interactive-program , command-file包含:
1 command #1
2 command #2
3 ...
而here document 的形式看上去是如下的样子:
1 #!/bin/bash
2 interactive-program
选择一个名字非常诡异的limit string将会避免命令列表和limit string重名的问题.
注意,某些时候here document 用在非交互工具和命令上的时候也会有好的效果, 比如,
wall
.
Example 17-1. 广播: 发送消息给每个登录上的用户
1 #!/bin/bash
2
3 wall
即使是某些不大可能的工具, 如vi也可以使用here document.
Example 17-2. 仿造文件: 创建一个两行的仿造文件
1 #!/bin/bash
2
3 # 用非交互的方式来使用'vi'编辑一个文件.
4 # 模仿'sed'.
5
6 E_BADARGS=65
7
8 if [ -z "$1" ]
9 then
10 echo "Usage: `basename $0` filename"
11 exit $E_BADARGS
12 fi
13
14 TARGETFILE=$1
15
16 # 在文件中插入两行, 然后保存.
17 #--------Begin here document-----------#
18 vi $TARGETFILE 就行,
28 #+ 事实上它是键.
29
30 # Bram Moolenaar指出这种方法不能正常地用在'vim'上, (译者注: Bram Moolenaar是vim作者)
31 #+ 因为可能会有终端的相互影响问题.
32
33 exit 0
上边的脚本也可以不用vi而用ex来实现. Here document 包含ex命令列表的做法足够形成自己的类别了, 叫ex scripts.
1 #!/bin/bash
2 # 把所有后缀为".txt"文件
3 #+ 中的"Smith"都替换成"Jones".
4
5 ORIGINAL=Smith
6 REPLACEMENT=Jones
7
8 for word in $(fgrep -l $ORIGINAL *.txt)
9 do
10 # -------------------------------------
11 ex $word
与"ex scripts"相似的是cat scripts.
Example 17-3. 使用cat的多行消息
1 #!/bin/bash
2
3 # 'echo' 对于打印单行消息是非常好的,
4 #+ 但是在打印消息块时可能就有点问题了.
5 # 'cat' here document可以解决这个限制.
6
7 cat $Newfile
- 选项用来标记here document的limit string (), 可以抑制输出时前边的tab(不是空格). 这可以增加一个脚本的可读性.
Example 17-4. 带有抑制tab功能的多行消息
1 #!/bin/bash
2 # 与之前的例子相同, 但是...
3
4 # - 选项对于here docutment来说,
here document 支持参数和命令替换. 所以也可以给here document的消息体传递不同的参数, 这样相应的也会修改输出.
Example 17-5. 使用参数替换的here document
1 #!/bin/bash
2 # 一个使用'cat'命令的here document, 使用了参数替换
3
4 # 不传命令行参数给它, ./scriptname
5 # 传一个命令行参数给它, ./scriptname Mortimer
6 # 传一个2个单词(用引号括起来)的命令行参数给它,
7 # ./scriptname "Mortimer Jones"
8
9 CMDLINEPARAM=1 # 所期望的最少的命令行参数的个数.
10
11 if [ $# -ge $CMDLINEPARAM ]
12 then
13 NAME=$1 # 如果命令行参数超过1个,
14 #+ 那么就只取第一个参数.
15 else
16 NAME="John Doe" # 默认情况下, 如果没有命令行参数的话.
17 fi
18
19 RESPONDENT="the author of this fine script"
20
21
22 cat
这是一个包含参数替换的here document的有用的脚本.
Example 17-6. 上传一个文件对到"Sunsite"的incoming目录
1 #!/bin/bash
2 # upload.sh
3
4 # 上传文件对(Filename.lsm, Filename.tar.gz)
5 #+ 到Sunsite/UNC (ibiblio.org)的incoming目录.
6 # Filename.tar.gz是自身的tar包.
7 # Filename.lsm是描述文件.
8 # Sunsite需要"lsm"文件, 否则就拒绝贡献.
9
10
11 E_ARGERROR=65
12
13 if [ -z "$1" ]
14 then
15 echo "Usage: `basename $0` Filename-to-upload"
16 exit $E_ARGERROR
17 fi
18
19
20 Filename=`basename $1` # 从文件名中去掉目录字符串.
21
22 Server="ibiblio.org"
23 Directory="/incoming/Linux"
24 # 在这里也不一定非得将上边的参数写死在这个脚本中,
25 #+ 可以使用命令行参数的方法来替换.
26
27 Password="your.e-mail.address" # 可以修改成相匹配的密码.
28
29 ftp -n $Server
在here document的开头引用或转义"limit string"会使得here document的消息体中的参数替换被禁用.
Example 17-7. 关闭参数替换
1 #!/bin/bash
2 # 一个使用'cat'的here document, 但是禁用了参数替换.
3
4 NAME="John Doe"
5 RESPONDENT="the author of this fine script"
6
7 cat
禁用了参数替换后, 将允许输出文本本身(译者注: 就是未转义的原文). 产生脚本甚至是程序代码就是这种用法的用途之一.
Example 17-8. 一个产生另外一个脚本的脚本
1 #!/bin/bash
2 # generate-script.sh
3 # 基于Albert Reiner的一个主意.
4
5 OUTFILE=generated.sh # 所产生文件的名字.
6
7
8 # -----------------------------------------------------------
9 # 'Here document包含了需要产生的脚本的代码.
10 (
11 cat $OUTFILE
32 # -----------------------------------------------------------
33
34 # 将'limit string'引用起来将会阻止上边
35 #+ here document的消息体中的变量扩展.
36 # 这会使得输出文件中的内容保持here document消息体中的原文.
37
38 if [ -f "$OUTFILE" ]
39 then
40 chmod 755 $OUTFILE
41 # 让所产生的文件具有可执行权限.
42 else
43 echo "Problem in creating file: \"$OUTFILE\""
44 fi
45
46 # 这个方法也用来产生
47 #+ C程序代码, Perl程序代码, Python程序代码, makefile,
48 #+ 和其他的一些类似的代码.
49 # (译者注: 中间一段没译的注释将会被here document打印出来)
50 exit 0
也可以将here document的输出保存到变量中.
1 variable=$(cat
同一脚本中的函数也可以接受here document的输出作为自身的参数.
Example 17-9. Here documents与函数
1 #!/bin/bash
2 # here-function.sh
3
4 GetPersonalData ()
5 {
6 read firstname
7 read lastname
8 read address
9 read city
10 read state
11 read zipcode
12 } # 这个函数无疑的看起来就一个交互函数, 但是...
13
14
15 # 给上边的函数提供输入.
16 GetPersonalData
也可以这么使用: 做一个假命令来从一个here document中接收输出. 这么做事实上就是创建了一个"匿名"的here document.
Example 17-10. "匿名" here Document
1 #!/bin/bash
2
3 :
![]()
上边所示技术的一种变化可以用来"注释"掉代码块.
Example 17-11. 注释掉一段代码块
1 #!/bin/bash
2 # commentblock.sh
3
4 :
![]()
关于这种小技巧的另一个应用就是能够产生自文档化(self-documenting)的脚本.
Example 17-12. 一个自文档化(self-documenting)的脚本
1 #!/bin/bash
2 # self-document.sh: 自文档化(self-documenting)的脚本
3 # Modification of "colm.sh".
4
5 DOC_REQUEST=70
6
7 if [ "$1" = "-h" -o "$1" = "--help" ] # 请求帮助.
8 then
9 echo; echo "Usage: $0 [directory-name]"; echo
10 sed --silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATIONXX$/p' "$0" |
11 sed -e '/DOCUMENTATIONXX$/d'; exit $DOC_REQUEST; fi
12
13
14 :
使用
cat 脚本
也能够完成相同的目的.
1 DOC_REQUEST=70
2
3 if [ "$1" = "-h" -o "$1" = "--help" ] # 请求帮助.
4 then # 使用"cat 脚本" . . .
5 cat
参见
Example A-27
可以了解更多关于自文档化脚本的好例子.
![]()
Here document创建临时文件, 但是这些文件将在打开后被删除, 并且不能够被任何其他进程所存取.
bash$ bash -c 'lsof -a -p $$ -d0'
> EOF
lsof 1213 bozo 0r REG 3,5 0 30386 /tmp/t1213-0-sh (deleted)
![]()
某些工具是不能工作在here document中的.
![]()
结束的limit string, 就是here document最后一行的limit string, 必须开始于第一个字符位置. 它的前面不能够有任何前置的空白. 而在这个limit string后边的空白也会引起异常问题. 空白将会阻止limit string的识别.(译者注: 下边这个脚本由于结束limit string的问题, 造成脚本无法结束, 所有内容全部被打印出来, 所以注释就不译了, 保持例子脚本的原样.)
1 #!/bin/bash
2
3 echo "----------------------------------------------------------------------"
4
5 cat
对于那些使用"here document"得非常复杂的任务, 最好考虑使用expect脚本语言, 这种语言就是为了达到向交互程序添加输入的目的而量身定做的.
17.1. Here Strings
here string 可以被认为是here document的一种定制形式. 除了COMMAND $WORD将被扩展并且被送入COMMAND的stdin中.
Example 17-13. 在一个文件的开头添加文本
1 #!/bin/bash
2 # prepend.sh: 在文件的开头添加文本.
3 #
4 # Kenny Stauffer所捐助的脚本例子,
5 #+ 被本文作者作了少量的修改.
6
7
8 E_NOSUCHFILE=65
9
10 read -p "File: " file # 'read'命令的 -p 参数显示提示符.
11 if [ ! -e "$file" ]
12 then # 如果没有这个文件那就进来.
13 echo "File $file not found."
14 exit $E_NOSUCHFILE
15 fi
16
17 read -p "Title: " title
18 cat - $file $file.new
19
20 echo "Modified file is $file.new"
21
22 exit 0
23
24 # 下边是'man bash'中的一段:
25 # Here Strings
26 # here document的一种变形,形式如下:
27 #
28 #
如果你觉得本文不错,可以订阅本站 |
Google Reader
|
Bloglines
|
抓虾
|
鲜果
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/52223/showart_458038.html |
|