Shell中Here document及打包代码(未完成)
2016-12-19 16:24
176 查看
COMMAND HERE ... HERE
limit string 用来划定命令序列的范围(译者注: 两个相同的limit string之间就是命令序列). 特殊符号 << 用来表识limit string. 这个符号具有重定向文件的输出到程序或命令的输入的作用. 与 interactive-program < command-file 很相象, command-file包含:
command #1 command #2 ...
而here document 的形式看上去是如下的样子:
#!/bin/bash interactive-program LimitString command #1 command #2 ... LimitString
选择一个名字非常诡异的limit string将会避免命令列表和limit string重名的问题.
注意,某些时候here document 用在非交互工具和命令上的时候也会有好的效果, 比如, wall.
——————————————————————————–
Example 1. 广播: 发送消息给每个登录上的用户
#!/bin/bash wall <<message-file #="" 0<="" code="" exit="" 是一种"小吃店"(快速但是比较脏)的只能使用一次的解决办法.="" 然而将消息模版嵌入到脚本中="">
--------------------------------------------------------------------------------
即使是某些不大可能的工具, 如vi也可以使用here document.
--------------------------------------------------------------------------------
Example 2. 仿造文件: 创建一个两行的仿造文件
#!/bin/bash # 用非交互的方式来使用'vi'编辑一个文件. # 模仿'sed'. E_BADARGS=65 if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit $E_BADARGS fi TARGETFILE=$1 # 在文件中插入两行, 然后保存. #--------Begin here document-----------# vi $TARGETFILE <<x23limitstringx23 #="" #----------end="" 1="" 2="" 就行, #+ 事实上它是键. # Bram Moolenaar指出这种方法不能正常地用在'vim'上, (译者注: Bram Moolenaar是vim作者) #+ 因为可能会有终端的相互影响问题. exit 0
--------------------------------------------------------------------------------
上边的脚本也可以不用vi而用ex来实现. Here document 包含ex命令列表的做法足够形成自己的类别了, 叫ex scripts.
#!/bin/bash # 把所有后缀为".txt"文件 #+ 中的"Smith"都替换成"Jones". ORIGINAL=Smith REPLACEMENT=Jones for word in $(fgrep -l $ORIGINAL *.txt) do # ------------------------------------- ex $word <
与"ex scripts"相似的是cat scripts.
--------------------------------------------------------------------------------
Example 3. 使用cat的多行消息
#!/bin/bash # 'echo' 对于打印单行消息是非常好的, #+ 但是在打印消息块时可能就有点问题了. # 'cat' here document可以解决这个限制. cat < $Newfile <<end-of-message "-------------------------------------="" #="" #+="" #--------------------------------------------="" -------------------------------------"="" 0="" 0".="" 1="" 2="" 3="" 4="" ^^^^^^^^^^="" code="" echo="" exit="" is="" last="" line="" message.="" of="" s.c.="" the="" this="" 下边的代码不会运行,="" 因为上边的"exit="" 指出下边代码也可以运行.="" 文本可能不包含双引号,="" 然而,="" 而不是stdout.="" 那么就会把输出写到文件$newfile中,="" 除非它们被转义.<="">
--------------------------------------------------------------------------------
- 选项用来标记here document的limit string (<<-LimitString), 可以抑制输出时前边的tab(不是空格). 这可以增加一个脚本的可读性.
--------------------------------------------------------------------------------
Example 4. 带有抑制tab功能的多行消息
#!/bin/bash # 与之前的例子相同, 但是... # - 选项对于here docutment来说,<<- #+ 可以抑制文档体前边的tab, #+ 而*不*是空格 *not* spaces. cat <<-ENDOFMESSAGE This is line 1 of the message. This is line 2 of the message. This is line 3 of the message. This is line 4 of the message. This is the last line of the message. ENDOFMESSAGE # 脚本在输出的时候左边将被刷掉. # 就是说每行前边的tab将不会显示. # 上边5行"消息"的前边都是tab, 不是空格. # 空格是不受<<-影响的. # 注意, 这个选项对于*嵌在*中间的tab没作用. exit 0
--------------------------------------------------------------------------------
here document 支持参数和命令替换. 所以也可以给here document的消息体传递不同的参数, 这样相应的也会修改输出.
--------------------------------------------------------------------------------
Example 5. 使用参数替换的here document
#!/bin/bash # 一个使用'cat'命令的here document, 使用了参数替换 # 不传命令行参数给它, ./scriptname # 传一个命令行参数给它, ./scriptname Mortimer # 传一个2个单词(用引号括起来)的命令行参数给它, # ./scriptname "Mortimer Jones" CMDLINEPARAM=1 # 所期望的最少的命令行参数的个数. if [ $# -ge $CMDLINEPARAM ] then NAME=$1 # 如果命令行参数超过1个, #+ 那么就只取第一个参数. else NAME="John Doe" # 默认情况下, 如果没有命令行参数的话. fi RESPONDENT="the author of this fine script" cat <
--------------------------------------------------------------------------------
这是一个包含参数替换的here document的有用的脚本.
--------------------------------------------------------------------------------
Example 6. 上传一个文件对到"Sunsite"的incoming目录
#!/bin/bash # upload.sh # 上传文件对(Filename.lsm, Filename.tar.gz) #+ 到Sunsite/UNC (ibiblio.org)的incoming目录. # Filename.tar.gz是自身的tar包. # Filename.lsm是描述文件. # Sunsite需要"lsm"文件, 否则就拒绝贡献. E_ARGERROR=65 if [ -z "$1" ] then echo "Usage: `basename $0` Filename-to-upload" exit $E_ARGERROR fi Filename=`basename $1` # 从文件名中去掉目录字符串. Server="ibiblio.org" Directory="/incoming/Linux" # 在这里也不一定非得将上边的参数写死在这个脚本中, #+ 可以使用命令行参数的方法来替换. Password="your.e-mail.address" # 可以修改成相匹配的密码. ftp -n $Server <<end-of-session "$filename.lsm"="" "$filename.tar.gz"="" "$password"="" #="" $directory="" -n="" 0<="" anonymous="" bell="" binary="" bye="" cd="" code="" end-of-session="" exit="" put="" user="" 响铃.="" 在每个文件传输后,="" 选项禁用自动登录.="">
--------------------------------------------------------------------------------
在here document的开头引用或转义"limit string"会使得here document的消息体中的参数替换被禁用.
--------------------------------------------------------------------------------
Example 7. 关闭参数替换
#!/bin/bash # 一个使用'cat'的here document, 但是禁用了参数替换. NAME="John Doe" RESPONDENT="the author of this fine script" cat <<'Endofmessage' Hello, there, $NAME. Greetings to you, $NAME, from $RESPONDENT. Endofmessage # 当"limit string"被引用或转义那么就禁用了参数替换. # 下边的两种方式具有相同的效果. # cat <<"Endofmessage" # cat <
--------------------------------------------------------------------------------
禁用了参数替换后, 将允许输出文本本身(译者注: 就是未转义的原文). 产生脚本甚至是程序代码就是这种用法的用途之一.
--------------------------------------------------------------------------------
Example 8. 一个产生另外一个脚本的脚本
#!/bin/bash # generate-script.sh # 基于Albert Reiner的一个主意. OUTFILE=generated.sh # 所产生文件的名字. # ----------------------------------------------------------- # 'Here document包含了需要产生的脚本的代码. ( cat <<'EOF' #!/bin/bash echo "This is a generated shell script." # Note that since we are inside a subshell, #+ we can't access variables in the "outside" script. echo "Generated file will be named: $OUTFILE" # Above line will not work as normally expected #+ because parameter expansion has been disabled. # Instead, the result is literal output. a=7 b=3 let "c = $a * $b" echo "c = $c" exit 0 EOF ) > $OUTFILE # ----------------------------------------------------------- # 将'limit string'引用起来将会阻止上边 #+ here document的消息体中的变量扩展. # 这会使得输出文件中的内容保持here document消息体中的原文. if [ -f "$OUTFILE" ] then chmod 755 $OUTFILE # 让所产生的文件具有可执行权限. else echo "Problem in creating file: "$OUTFILE"" fi # 这个方法也用来产生 #+ C程序代码, Perl程序代码, Python程序代码, makefile, #+ 和其他的一些类似的代码. # (译者注: 中间一段没译的注释将会被here document打印出来) exit 0
--------------------------------------------------------------------------------
也可以将here document的输出保存到变量中.
variable=$(cat <
同一脚本中的函数也可以接受here document的输出作为自身的参数.
--------------------------------------------------------------------------------
Example 9. Here documents与函数
#!/bin/bash # here-function.sh GetPersonalData () { read firstname read lastname read address read city read state read zipcode } # 这个函数无疑的看起来就一个交互函数, 但是... # 给上边的函数提供输入. GetPersonalData <<record001 "$address"="" "$city,="" "$firstname="" $lastname"="" $state="" $zipcode"="" 0<="" baltimore="" bozeman="" bozo="" code="" dr.="" echo="" exit="" md="" nondescript="" record001="">
--------------------------------------------------------------------------------
也可以这么使用: 做一个假命令来从一个here document中接收输出. 这么做事实上就是创建了一个"匿名"的here document.
--------------------------------------------------------------------------------
Example 10. "匿名" here Document
#!/bin/bash : <
--------------------------------------------------------------------------------
上边所示技术的一种变化可以用来"注释"掉代码块.
--------------------------------------------------------------------------------
Example 11. 注释掉一段代码块
#!/bin/bash # commentblock.sh : <
--------------------------------------------------------------------------------
关于这种小技巧的另一个应用就是能够产生自文档化(self-documenting)的脚本.
--------------------------------------------------------------------------------
Example 12. 一个自文档化(self-documenting)的脚本
#!/bin/bash # self-document.sh: 自文档化(self-documenting)的脚本 # Modification of "colm.sh". DOC_REQUEST=70 if [ "$1" = "-h" -o "$1" = "--help" ] # 请求帮助. then echo; echo "Usage: $0 [directory-name]"; echo sed --silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATIONXX$/p' "$0" | sed -e '/DOCUMENTATIONXX$/d'; exit $DOC_REQUEST; fi : <
--------------------------------------------------------------------------------
使用cat 脚本 也能够完成相同的目的.
DOC_REQUEST=70 if [ "$1" = "-h" -o "$1" = "--help" ] # 请求帮助. then # 使用"cat 脚本" . . . cat <
参见 Example A-27 可以了解更多关于自文档化脚本的好例子.
Here document创建临时文件, 但是这些文件将在打开后被删除, 并且不能够被任何其他进程所存取.
bash$ bash -c 'lsof -a -p $$ -d0' << EOF
> 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的问题, 造成脚本无法结束, 所有内容全部被打印出来, 所以注释就不译了, 保持例子脚本的原样.)
#!/bin/bash echo "----------------------------------------------------------------------" cat <
对于那些使用"here document"得非常复杂的任务, 最好考虑使用expect脚本语言, 这种语言就是为了达到向交互程序添加输入的目的而量身定做的.
17.1. Here Strings
here string 可以被认为是here document的一种定制形式. 除了COMMAND <<<$WORD 就什么都没有了, $WORD将被扩展并且被送入COMMAND的stdin中.
--------------------------------------------------------------------------------
Example 13. 在一个文件的开头添加文本
#!/bin/bash # prepend.sh: 在文件的开头添加文本. # # Kenny Stauffer所捐助的脚本例子, #+ 被本文作者作了少量的修改. E_NOSUCHFILE=65 read -p "File: " file # 'read'命令的 -p 参数显示提示符. if [ ! -e "$file" ] then # 如果没有这个文件那就进来. echo "File $file not found." exit $E_NOSUCHFILE fi read -p "Title: " title cat - $file <<<$title > $file.new echo "Modified file is $file.new" exit 0 # 下边是'man bash'中的一段: # Here Strings # here document的一种变形,形式如下: # # <<
相关文章推荐
- 利用Here Document,打包C(或其他程序语言)的原始代码
- shell脚本利用Here Document ,打包C的源码并编译生成再执行。shell携代攻击程序
- 利用HERE Document携带C原代码
- 利用HERE Document携带C原代码
- Shell中的cat<<EOF (here document) (转)
- shell here document的一些操作(交互式程序读写操作)
- 十五、Shell输入输出重定向:Shell Here Document,/dev/null文件
- 利用Here Document,打包C(或其他)的原始码
- Shell输入输出重定向:Shell Here Document,/dev/null文件
- Shell输入输出重定向:Shell Here Document,/dev/null文件
- shell here document 应用实例--shell控制数据库
- Shell输入输出重定向:Shell Here Document,/dev/null文件
- Shell输入输出重定向:Shell Here Document,/dev/null文件
- Shell输入输出重定向:Shell Here Document,/dev/null文件
- 利用HERE Document携带C原代码
- 【Shell脚本学习24】Shell输入输出重定向:Shell Here Document,/dev/null文件
- Shell输入输出重定向:Shell Here Document,/dev/null文件 .sh文件包含执行
- Shell之Here Document
- Shell输入输出重定向:Shell Here Document,/dev/null文件
- 二十二、Shell输入输出重定向:Shell Here Document,/dev/null文件