📄 here-docs.html
字号:
5 RESPONDENT="the author of this fine script" 6 7 cat <<'Endofmessage' 8 9 Hello, there, $NAME. 10 Greetings to you, $NAME, from $RESPONDENT. 11 12 Endofmessage 13 14 # 如果"limit string"被引用或转义的话, 那么就禁用了参数替换. 15 # 下边的两种方式具有相同的效果. 16 # cat <<"Endofmessage" 17 # cat <<\Endofmessage 18 19 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>禁用了参数替换后, 将允许输出文本本身(译者注: 就是未转义的原文). 如果你想产生脚本甚至是程序代码的话, 那么可以使用这种办法. </P><DIVCLASS="EXAMPLE"><HR><ANAME="GENERATESCRIPT"></A><P><B>例子 17-8. 生成另外一个脚本的脚本</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # generate-script.sh 3 # 这个脚本的诞生基于Albert Reiner的一个主意. 4 5 OUTFILE=generated.sh # 所产生文件的名字. 6 7 8 # ----------------------------------------------------------- 9 # 'Here document包含了需要产生的脚本的代码. 10 ( 11 cat <<'EOF' 12 #!/bin/bash 13 14 echo "This is a generated shell script." 15 # Note that since we are inside a subshell, 16 #+ we can't access variables in the "outside" script. 17 18 echo "Generated file will be named: $OUTFILE" 19 # Above line will not work as normally expected 20 #+ because parameter expansion has been disabled. 21 # Instead, the result is literal output. 22 23 a=7 24 b=3 25 26 let "c = $a * $b" 27 echo "c = $c" 28 29 exit 0 30 EOF 31 ) > $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</PRE></FONT></TD></TR></TABLE><HR></DIV><P> 也可以将here document的输出保存到变量中. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 variable=$(cat <<SETVAR 2 This variable 3 runs over multiple lines. 4 SETVAR) 5 6 echo "$variable"</PRE></FONT></TD></TR></TABLE> </P><P>A here document can supply input to a function in the same script.</P><DIVCLASS="EXAMPLE"><HR><ANAME="HF"></A><P><B>例子 17-9. Here document与函数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 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 <<RECORD001 17 Bozo 18 Bozeman 19 2726 Nondescript Dr. 20 Baltimore 21 MD 22 21226 23 RECORD001 24 25 26 echo 27 echo "$firstname $lastname" 28 echo "$address" 29 echo "$city, $state $zipcode" 30 echo 31 32 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P><ANAME="ANONHEREDOC0"></A></P><P>也可以这么使用<SPANCLASS="TOKEN">:</SPAN>(冒号), 做一个假命令来从一个here document中接收输出. 这么做事实上就是创建了一个<SPANCLASS="QUOTE">"匿名"</SPAN>的here document. </P><DIVCLASS="EXAMPLE"><HR><ANAME="ANONHEREDOC"></A><P><B>例子 17-10. <SPANCLASS="QUOTE">"匿名"</SPAN>的here Document</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 : <<TESTVARIABLES 4 ${HOSTNAME?}${USER?}${MAIL?} # 如果其中某个变量没被设置, 那么就打印错误信息. 5 TESTVARIABLES 6 7 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P><ANAME="CBLOCK1"></A></P><DIVCLASS="TIP"><P></P><TABLECLASS="TIP"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/tip.gif"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>上边所示技术的一种变化, 可以用来<SPANCLASS="QUOTE">"注释"</SPAN>掉代码块. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="COMMENTBLOCK"></A><P><B>例子 17-11. 注释掉一段代码块</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # commentblock.sh 3 4 : <<COMMENTBLOCK 5 echo "This line will not echo." 6 This is a comment line missing the "#" prefix. 7 This is another comment line missing the "#" prefix. 8 9 &*@!!++= 10 The above line will cause no error message, 11 because the Bash interpreter will ignore it. 12 COMMENTBLOCK 13 14 echo "Exit value of above \"COMMENTBLOCK\" is $?." # 0 15 # 这里将不会显示任何错误. 16 17 18 # 上边的这种技术当然也可以用来注释掉 19 #+ 一段正在使用的代码, 如果你有某些特定调试要求的话. 20 # 这比在每行前边都敲入"#"来得方便的多, 21 #+ 而且如果你想恢复的话, 还得将添加上的"#"删除掉. 22 23 : <<DEBUGXXX 24 for file in * 25 do 26 cat "$file" 27 done 28 DEBUGXXX 29 30 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="TIP"><P></P><TABLECLASS="TIP"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/tip.gif"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>关于这种小技巧的另一个应用就是能够产生<SPANCLASS="QUOTE">"自文档化(self-documenting)"</SPAN>的脚本. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="SELFDOCUMENT"></A><P><B>例子 17-12. 一个自文档化(self-documenting)的脚本</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # self-document.sh: 自文档化(self-documenting)的脚本 3 # 修改于"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 : <<DOCUMENTATIONXX 15 List the statistics of a specified directory in tabular format. 16 --------------------------------------------------------------- 17 The command line parameter gives the directory to be listed. 18 If no directory specified or directory specified cannot be read, 19 then list the current working directory. 20 21 DOCUMENTATIONXX 22 23 if [ -z "$1" -o ! -r "$1" ] 24 then 25 directory=. 26 else 27 directory="$1" 28 fi 29 30 echo "Listing of "$directory":"; echo 31 (printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n" \ 32 ; ls -l "$directory" | sed 1d) | column -t 33 34 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>使用<AHREF="here-docs.html#CATSCRIPTREF">cat脚本</A>也能够完成相同的目的. </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 DOC_REQUEST=70 2 3 if [ "$1" = "-h" -o "$1" = "--help" ] # 请求帮助. 4 then # 使用"cat脚本" . . . 5 cat <<DOCUMENTATIONXX 6 List the statistics of a specified directory in tabular format. 7 --------------------------------------------------------------- 8 The command line parameter gives the directory to be listed. 9 If no directory specified or directory specified cannot be read, 10 then list the current working directory. 11 12 DOCUMENTATIONXX 13 exit $DOC_REQUEST 14 fi</PRE></FONT></TD></TR></TABLE> </P><P>请参考<AHREF="contributed-scripts.html#ISSPAMMER2">例子 A-28</A>可以看到更多关于<SPANCLASS="QUOTE">"自文档化"</SPAN>脚本的好例子. </P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>Here document创建临时文件, 但是这些文件将在打开后被删除, 并且不能够被任何其他进程所访问. </P><P> <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">bash -c 'lsof -a -p $$ -d0' << EOF</KBD><SAMPCLASS="PROMPT">> </SAMP><KBDCLASS="USERINPUT">EOF</KBD><SAMPCLASS="COMPUTEROUTPUT">lsof 1213 bozo 0r REG 3,5 0 30386 /tmp/t1213-0-sh (deleted)</SAMP> </PRE></FONT></TD></TR></TABLE> </P></TD></TR></TABLE></DIV><DIVCLASS="CAUTION"><P></P><TABLECLASS="CAUTION"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/caution.gif"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>某些工具是不能放入<EM>here document</EM>中运行的. </P></TD></TR></TABLE></DIV><P><ANAME="INDENTEDLS"></A></P><DIVCLASS="WARNING"><P></P><TABLECLASS="WARNING"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/warning.gif"HSPACE="5"ALT="Warning"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>结尾的<EM>limit string</EM>, 就是here document最后一行的limit string, 必须从<EM>第一个</EM>字符开始. 它的前面不能够有任何<EM>前置的空白</EM>. 而在这个limit string后边的空白也会引起异常. 空白将会阻止limit string的识别. (译者注: 下边这个脚本由于结束limit string的问题, 造成脚本无法结束, 所有内容全部被打印出来, 所以注释就不译了, 保持这个例子脚本的原样.) </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 echo "----------------------------------------------------------------------" 4 5 cat <<LimitString 6 echo "This is line 1 of the message inside the here document." 7 echo "This is line 2 of the message inside the here document." 8 echo "This is the final line of the message inside the here document." 9 LimitString 10 #^^^^Indented limit string. Error! This script will not behave as expected. 11 12 echo "----------------------------------------------------------------------" 13 14 # These comments are outside the 'here document', 15 #+ and should not echo. 16 17 echo "Outside the here document." 18 19 exit 0 20 21 echo "This line had better not echo." # Follows an 'exit' command.</PRE></FONT></TD></TR></TABLE> </P></TD></TR></TABLE></DIV><P>对于那些使用<SPANCLASS="QUOTE">"here document"</SPAN>, 并且非常复杂的任务, 最好考虑使用<BCLASS="COMMAND">expect</B>脚本语言, 这种语言就是为了达到向交互程序添加输入的目的而量身定做的. </P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="redirapps.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">首页</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="x13628.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">重定向的应用</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part3.html"ACCESSKEY="U">上一级</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Here String</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -