⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 here-docs.html

📁 BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>Here Document</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="进阶"HREF="part3.html"><LINKREL="PREVIOUS"TITLE="重定向的应用"HREF="redirapps.html"><LINKREL="NEXT"TITLE="Here String"HREF="x13628.html"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="redirapps.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="x13628.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="HERE-DOCS"></A>17. Here Document</H1><TABLEBORDER="0"WIDTH="100%"CELLSPACING="0"CELLPADDING="0"CLASS="EPIGRAPH"><TR><TDWIDTH="45%">&nbsp;</TD><TDWIDTH="45%"ALIGN="LEFT"VALIGN="TOP"><I><P><I>Here and now, boys.</I></P></I></TD></TR><TR><TDWIDTH="45%">&nbsp;</TD><TDWIDTH="45%"ALIGN="RIGHT"VALIGN="TOP"><I><SPANCLASS="ATTRIBUTION">Aldous Huxley, <SPANCLASS="QUOTE">"Island"</SPAN></SPAN></I></TD></TR></TABLE><P><ANAME="HEREDOCREF"></A></P><P>一个<ICLASS="FIRSTTERM">here document</I>就是一段带有特殊目的的代码段. 	它使用<AHREF="io-redirection.html#IOREDIRREF">I/O重定向</A>的形式将一个命令序列传递到一个交互程序或者命令中, 比如<AHREF="communications.html#FTPREF">ftp</A>, <AHREF="basic.html#CATREF">cat</A>,	或者<ICLASS="FIRSTTERM">ex</I>文本编辑器. </P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;COMMAND &#60;&#60;InputComesFromHERE  2&nbsp;...  3&nbsp;InputComesFromHERE</PRE></FONT></TD></TR></TABLE></P><P><ICLASS="FIRSTTERM">limit string</I>用来界定命令序列的范围(译者注: 	两个相同的limit string之间就是命令序列). 	特殊符号<SPANCLASS="TOKEN">&#60;&#60;</SPAN>用来标识limit string. 	这个符号的作用就是将文件的输出重定向到程序或命令的<TTCLASS="FILENAME">stdin</TT>中. 	与<KBDCLASS="USERINPUT">interactive-program &#60;	command-file</KBD>很相似, 其中<TTCLASS="FILENAME">command-file</TT>包含: 	  <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;command #1  2&nbsp;command #2  3&nbsp;...</PRE></FONT></TD></TR></TABLE></P><P>而<EM>here document</EM>看上去是下面这个样子: </P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;interactive-program &#60;&#60;LimitString  3&nbsp;command #1  4&nbsp;command #2  5&nbsp;...  6&nbsp;LimitString</PRE></FONT></TD></TR></TABLE></P><P>选择一个名字非常诡异<EM>limit string</EM>能够有效的避免命令列表与<EM>limit string</EM>重名的问题. </P><P>注意, 某些情况下, 把<EM>here document</EM>用在非交互工具或命令中, 也会取得非常好的效果, 	比如, <AHREF="system.html#WALLREF">wall</A>. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX70"></A><P><B>例子 17-1. <BCLASS="COMMAND">广播</B>: 将消息发送给每个登陆的用户</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;wall &#60;&#60;zzz23EndOfMessagezzz23  4&nbsp;E-mail your noontime orders for pizza to the system administrator.  5&nbsp;    (Add an extra dollar for anchovy or mushroom topping.)  6&nbsp;# 附加的消息文本放在这里.   7&nbsp;# 注意: 'wall'命令会把注释行也打印出来.   8&nbsp;zzz23EndOfMessagezzz23  9&nbsp; 10&nbsp;# 当然, 更有效率的做法是:  11&nbsp;#         wall &#60;message-file 12&nbsp;#  然而, 将消息模版嵌入到脚本中 13&nbsp;#+ 只是一种"小吃店"(译者注: 方便但是不卫生)的做法, 而且这种做法是一次性的.  14&nbsp; 15&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>对于某些看上去不太可能的工具, 		  比如<ICLASS="FIRSTTERM">vi</I>,         也能够使用<EM>here document</EM>. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX69"></A><P><B>例子 17-2. <BCLASS="COMMAND">虚拟文件</B>: 创建一个2行的虚拟文件</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;# 用非交互的方式来使用'vi'编辑一个文件.   4&nbsp;# 模仿'sed'.  5&nbsp;  6&nbsp;E_BADARGS=65  7&nbsp;  8&nbsp;if [ -z "$1" ]  9&nbsp;then 10&nbsp;  echo "Usage: `basename $0` filename" 11&nbsp;  exit $E_BADARGS 12&nbsp;fi 13&nbsp; 14&nbsp;TARGETFILE=$1 15&nbsp; 16&nbsp;# 在文件中插入两行, 然后保存.  17&nbsp;#--------Begin here document-----------# 18&nbsp;vi $TARGETFILE &#60;&#60;x23LimitStringx23 19&nbsp;i 20&nbsp;This is line 1 of the example file. 21&nbsp;This is line 2 of the example file. 22&nbsp;^[ 23&nbsp;ZZ 24&nbsp;x23LimitStringx23 25&nbsp;#----------End here document-----------# 26&nbsp; 27&nbsp;#  注意上边^[是一个转义符, 键入Ctrl+v &#60;Esc&#62;就行, 28&nbsp;#+ 事实上它是&#60;Esc&#62;键;.  29&nbsp; 30&nbsp;#  Bram Moolenaar指出这种方法不能使用在'vim'上, (译者注: Bram Moolenaar是vim作者) 31&nbsp;#+ 因为可能会存在终端相互影响的问题.  32&nbsp; 33&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>		  上边的脚本也可以不用<BCLASS="COMMAND">vi</B>而改用<BCLASS="COMMAND">ex</B>来实现, 		  <EM>here document</EM>包含<BCLASS="COMMAND">ex</B>命令列表的形式足以形成自己的类别了, 		  称为<ICLASS="FIRSTTERM">ex script</I>. 	  <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;#  把所有后缀为".txt"文件  3&nbsp;#+ 中的"Smith"都替换成"Jones".   4&nbsp;  5&nbsp;ORIGINAL=Smith  6&nbsp;REPLACEMENT=Jones  7&nbsp;  8&nbsp;for word in $(fgrep -l $ORIGINAL *.txt)  9&nbsp;do 10&nbsp;  # ------------------------------------- 11&nbsp;  ex $word &#60;&#60;EOF 12&nbsp;  :%s/$ORIGINAL/$REPLACEMENT/g 13&nbsp;  :wq 14&nbsp;EOF 15&nbsp;  # :%s是"ex"的替换命令. (译者注: 与vi和vim的基本命令相同) 16&nbsp;  # :wq是保存并退出的意思.  17&nbsp;  # ------------------------------------- 18&nbsp;done</PRE></FONT></TD></TR></TABLE>	</P><P><ANAME="CATSCRIPTREF"></A></P><P>与<SPANCLASS="QUOTE">"ex script"</SPAN>相似的是<ICLASS="FIRSTTERM">cat script</I>. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX71"></A><P><B>例子 17-3. 使用<BCLASS="COMMAND">cat</B>的多行消息</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;#  'echo'对于打印单行消息来说是非常好用的,   4&nbsp;#+  但是在打印消息块时可能就有点问题了.   5&nbsp;#   'cat' here document可以解决这个限制.   6&nbsp;  7&nbsp;cat &#60;&#60;End-of-message  8&nbsp;-------------------------------------  9&nbsp;This is line 1 of the message. 10&nbsp;This is line 2 of the message. 11&nbsp;This is line 3 of the message. 12&nbsp;This is line 4 of the message. 13&nbsp;This is the last line of the message. 14&nbsp;------------------------------------- 15&nbsp;End-of-message 16&nbsp; 17&nbsp;#  用下边这行代替上边的第7行,  18&nbsp;#+   cat &#62; $Newfile &#60;&#60;End-of-message 19&nbsp;#+       ^^^^^^^^^^ 20&nbsp;#+ 那么就会把输出写到文件$Newfile中, 而不是stdout.  21&nbsp; 22&nbsp;exit 0 23&nbsp; 24&nbsp; 25&nbsp;#-------------------------------------------- 26&nbsp;# 下边的代码不会运行, 因为上边有"exit 0".  27&nbsp; 28&nbsp;# S.C. 指出下边代码也能够达到相同目的.  29&nbsp;echo "------------------------------------- 30&nbsp;This is line 1 of the message. 31&nbsp;This is line 2 of the message. 32&nbsp;This is line 3 of the message. 33&nbsp;This is line 4 of the message. 34&nbsp;This is the last line of the message. 35&nbsp;-------------------------------------" 36&nbsp;# 然而, 文本中可能不允许包含双引号, 除非它们被转义. </PRE></FONT></TD></TR></TABLE><HR></DIV><P><CODECLASS="OPTION">-</CODE>选项用来标记here document的limit string		  (<KBDCLASS="USERINPUT">&#60;&#60;-LimitString</KBD>), 		  可以抑制输出时前边的tab(不是空格). 这么做可以增加一个脚本的可读性. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX71A"></A><P><B>例子 17-4. 带有抑制tab功能的多行消息</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 与之前的例子相同, 但是...   3&nbsp;  4&nbsp;#  - 选项对于here docutment来说,   5&nbsp;#+ &#60;&#60;-可以抑制文档体前边的tab,   6&nbsp;#+ 而*不*是空格.   7&nbsp;  8&nbsp;cat &#60;&#60;-ENDOFMESSAGE  9&nbsp;	This is line 1 of the message. 10&nbsp;	This is line 2 of the message. 11&nbsp;	This is line 3 of the message. 12&nbsp;	This is line 4 of the message. 13&nbsp;	This is the last line of the message. 14&nbsp;ENDOFMESSAGE 15&nbsp;# 脚本在输出的时候左边将被刷掉.  16&nbsp;# 就是说每行前边的tab将不会显示.  17&nbsp; 18&nbsp;# 上边5行"消息"的前边都是tab, 而不是空格.  19&nbsp;# 空格是不受&#60;&#60;-影响的.  20&nbsp; 21&nbsp;# 注意, 这个选项对于*嵌在*中间的tab没作用.  22&nbsp; 23&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P><EM>here document</EM>支持参数和命令替换. 		  所以也可以给here document的消息体传递不同的参数, 		  这样相应的也会修改输出. 	</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX71B"></A><P><B>例子 17-5. 使用参数替换的here document</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 一个使用'cat'命令的here document, 使用了参数替换.   3&nbsp;  4&nbsp;# 不传命令行参数给它,   ./scriptname  5&nbsp;# 传一个命令行参数给它,   ./scriptname Mortimer  6&nbsp;# 传一个包含2个单词(用引号括起来)的命令行参数给它,   7&nbsp;#                           ./scriptname "Mortimer Jones"  8&nbsp;  9&nbsp;CMDLINEPARAM=1     #  所期望的最少的命令行参数个数.  10&nbsp; 11&nbsp;if [ $# -ge $CMDLINEPARAM ] 12&nbsp;then 13&nbsp;  NAME=$1          #  如果命令行参数超过1个,  14&nbsp;                   #+ 那么就只取第一个参数.  15&nbsp;else 16&nbsp;  NAME="John Doe"  #  默认情况下, 如果没有命令行参数的话.  17&nbsp;fi   18&nbsp; 19&nbsp;RESPONDENT="the author of this fine script"   20&nbsp;   21&nbsp; 22&nbsp;cat &#60;&#60;Endofmessage 23&nbsp; 24&nbsp;Hello, there, $NAME. 25&nbsp;Greetings to you, $NAME, from $RESPONDENT. 26&nbsp; 27&nbsp;# This comment shows up in the output (why?). 28&nbsp; 29&nbsp;Endofmessage 30&nbsp; 31&nbsp;# 注意上边的空行也打印输出,  32&nbsp;# 而上边那行"注释"当然也会打印到输出.  33&nbsp;# (译者注: 这就是为什么不翻译那行注释的原因, 尽量保持代码的原样) 34&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>这是一个非常有用的脚本, 其中使用了包含参数替换的here document.  </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX72"></A><P><B>例子 17-6. 上传一个文件对到<SPANCLASS="QUOTE">"Sunsite"</SPAN>的incoming目录</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# upload.sh  3&nbsp;  4&nbsp;#  上传这一对文件(Filename.lsm, Filename.tar.gz)  5&nbsp;#+ 到Sunsite/UNC (ibiblio.org)的incoming目录.   6&nbsp;#  Filename.tar.gz是自身的tar包.   7&nbsp;#  Filename.lsm是描述文件.   8&nbsp;#  Sunsite需要"lsm"文件, 否则就拒绝上传.   9&nbsp; 10&nbsp; 11&nbsp;E_ARGERROR=65 12&nbsp; 13&nbsp;if [ -z "$1" ] 14&nbsp;then 15&nbsp;  echo "Usage: `basename $0` Filename-to-upload" 16&nbsp;  exit $E_ARGERROR 17&nbsp;fi   18&nbsp; 19&nbsp; 20&nbsp;Filename=`basename $1`           # 从文件名中去掉目录字符串.  21&nbsp; 22&nbsp;Server="ibiblio.org" 23&nbsp;Directory="/incoming/Linux" 24&nbsp;#  在这里也不一定非得将上边的参数写死在这个脚本中,  25&nbsp;#+ 可以使用命令行参数的方法来替换.  26&nbsp; 27&nbsp;Password="your.e-mail.address"   # 可以修改成相匹配的密码.  28&nbsp; 29&nbsp;ftp -n $Server &#60;&#60;End-Of-Session 30&nbsp;# -n选项禁用自动登录.  31&nbsp; 32&nbsp;user anonymous "$Password" 33&nbsp;binary 34&nbsp;bell                             # 在每个文件传输后, 响铃.  35&nbsp;cd $Directory 36&nbsp;put "$Filename.lsm" 37&nbsp;put "$Filename.tar.gz" 38&nbsp;bye 39&nbsp;End-Of-Session 40&nbsp; 41&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>在here document的开头, 引用或转义<SPANCLASS="QUOTE">"limit string"</SPAN>, 		  会使得here document消息体中的参数替换被禁用. 	</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX71C"></A><P><B>例子 17-7. 关闭参数替换</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;#  一个使用'cat'的here document, 但是禁用了参数替换.   3&nbsp;  4&nbsp;NAME="John Doe"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -