escapingsection.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 760 行
HTML
760 行
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>转义</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="引用"HREF="quoting.html"><LINKREL="PREVIOUS"TITLE="引用变量"HREF="quotingvar.html"><LINKREL="NEXT"TITLE="退出和退出状态码"HREF="exit-status.html"></HEAD><BODYCLASS="SECT1"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="quotingvar.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">5. 引用</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="exit-status.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="ESCAPINGSECTION">5.2. 转义</A></H1><P><ANAME="ESCP"></A><ICLASS="FIRSTTERM">转义</I>是一种引用单个字符的方法. 一个前面放上<SPANCLASS="TOKEN">转义符</SPAN> (<SPANCLASS="TOKEN">\</SPAN>)的字符就是告诉shell这个字符按照字面的意思进行解释, 换句话说, 就是这个字符失去了它的特殊含义. </P><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>在某些特定的命令和工具中, 比如<AHREF="internal.html#ECHOREF">echo</A>和<AHREF="sedawk.html#SEDREF">sed</A>, 转义符往往会起到相反效果 - 它反倒可能会引发出这个字符的特殊含义. </P></TD></TR></TABLE></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="SPM"></A>特定的转义符的特殊的含义</B></P><DL><DT><BCLASS="COMMAND">echo</B>和<BCLASS="COMMAND">sed</B>命令中使用</DT><DD><P></P></DD><DT><SPANCLASS="TOKEN">\n</SPAN></DT><DD><P>表示新的一行</P></DD><DT><SPANCLASS="TOKEN">\r</SPAN></DT><DD><P>表示回车</P></DD><DT><SPANCLASS="TOKEN">\t</SPAN></DT><DD><P>表示水平制表符</P></DD><DT><SPANCLASS="TOKEN">\v</SPAN></DT><DD><P>表示垂直制表符</P></DD><DT><SPANCLASS="TOKEN">\b</SPAN></DT><DD><P>表示后退符</P></DD><DT><SPANCLASS="TOKEN">\a</SPAN></DT><DD><P>表示<SPANCLASS="QUOTE">"alert"</SPAN>(蜂鸣或者闪烁)</P></DD><DT><SPANCLASS="TOKEN">\0xx</SPAN></DT><DD><P>转换为八进制的ASCII码, 等价于<TTCLASS="REPLACEABLE"><I>0xx</I></TT></P><DIVCLASS="EXAMPLE"><HR><ANAME="ESCAPED"></A><P><B>例子 5-2. 转义符</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 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" # 打印4个垂直制表符. 11 echo "==============" 12 13 echo "QUOTATION MARK" 14 echo -e "\042" # 打印" (引号, 8进制的ASCII 码就是42). 15 echo "==============" 16 17 # 如果使用$'\X'结构,那-e选项就不必要了. 18 echo; echo "NEWLINE AND BEEP" 19 echo $'\n' # 新行. 20 echo $'\a' # 警告(蜂鸣). 21 22 echo "===============" 23 echo "QUOTATION MARKS" 24 # 版本2以后Bash允许使用$'\nnn'结构. 25 # 注意在这里, '\nnn\'是8进制的值. 26 echo $'\t \042 \t' # 被水平制表符括起来的引号("). 27 28 # 当然,也可以使用16进制的值,使用$'\xhhh' 结构. 29 echo $'\t \x22 \t' # 被水平制表符括起来的引号("). 30 # 感谢, Greg Keraunen, 指出了这点. 31 # 早一点的Bash版本允许'\x022'这种形式. 32 echo "===============" 33 echo 34 35 36 # 分配ASCII字符到变量中. 37 # ---------------------------------------- 38 quote=$'\042' # " 被赋值到变量中. 39 echo "$quote This is a quoted string, $quote and this lies outside the quotes." 40 41 echo 42 43 # 变量中的连续的ASCII字符. 44 triple_underline=$'\137\137\137' # 137是八进制的'_'. 45 echo "$triple_underline UNDERLINE $triple_underline" 46 47 echo 48 49 ABC=$'\101\102\103\010' # 101, 102, 103是八进制码的A, B, C. 50 echo $ABC 51 52 echo; echo 53 54 escape=$'\033' # 033 是八进制码的esc. 55 echo "\"escape\" echoes as $escape" 56 # 没有变量被输出. 57 58 echo; echo 59 60 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>参考<AHREF="bashver2.html#EX77">例子 34-1</A>, 这是关于<KBDCLASS="USERINPUT">$' '</KBD>字符串扩展结构的一个例子. </P></DD><DT><SPANCLASS="TOKEN">\"</SPAN></DT><DD><P>表示引号字面的意思</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 echo "Hello" # Hello 2 echo "\"Hello\", he said." # "Hello", he said.</PRE></FONT></TD></TR></TABLE></P></DD><DT><SPANCLASS="TOKEN">\$</SPAN></DT><DD><P>表示$本身子面的含义(跟在<SPANCLASS="TOKEN">\$</SPAN>后边的变量名将不能引用变量的值)</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 echo "\$variable01" # 结果是$variable01</PRE></FONT></TD></TR></TABLE></P></DD><DT><SPANCLASS="TOKEN">\\</SPAN></DT><DD><P>表示反斜线字面的意思</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 echo "\\" # 结果是\ 2 3 # 反之 . . . 4 5 echo "\" # 如果从命令行调用的话, 会出现SP2, 也就是2级提示符(译者注: 提示你命令不全, 在添加一个"就好了. 6 # 如果在脚本中调用的话, 那么会报错. </PRE></FONT></TD></TR></TABLE></P></DD></DL></DIV><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><SPANCLASS="TOKEN">\</SPAN>的行为依赖于它自身是否被转义, 被引用(""), 或者是否出现在<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>或<AHREF="here-docs.html#HEREDOCREF">here document</A>中. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 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 27 28 # 这些例子是由Stephane Chazelas所提供的.</PRE></FONT></TD></TR></TABLE> </P><P>赋值给变量的字符串的元素也会被转义, 但是不能把一个单独的转义符赋值给变量. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 variable=\ 2 echo "$variable" 3 # 不能正常运行 - 会报错: 4 # test.sh: : command not found 5 # 一个"裸体的"转义符是不能够安全的赋值给变量的. 6 # 7 # 事实上在这里"\"转义了一个换行符(变成了续航符的含义), 8 #+ 效果就是 variable=echo "$variable" 9 #+ 不可用的变量赋值 10 11 variable=\ 12 23skidoo 13 echo "$variable" # 23skidoo 14 # 这句是可以的, 因为 15 #+ 第2行是一个可用的变量赋值. 16 17 variable=\ 18 # \^ 转义一个空格 19 echo "$variable" # 显示空格 20 21 variable=\\ 22 echo "$variable" # \ 23 24 variable=\\\ 25 echo "$variable" 26 # 不能正常运行 - 报错: 27 # test.sh: \: command not found 28 # 29 # 第一个转义符把第2个\转义了,但是第3个又变成"裸体的"了, 30 #+ 与上边的例子的原因相同. 31 32 variable=\\\\ 33 echo "$variable" # \\ 34 # 第2和第4个反斜线被转义了. 35 # 这是正确的. </PRE></FONT></TD></TR></TABLE> </P></TD></TR></TABLE></DIV><P>转义一个空格会阻止命令行参数列表的<SPANCLASS="QUOTE">"单词分割"</SPAN>问题. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 file_list="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7" 2 # 列出的文件都作为命令的参数. 3 4 # 加两个文件到参数列表中, 列出所有的文件信息. 5 ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list 6 7 echo "-------------------------------------------------------------------------" 8 9 # 如果我们将上边的两个空个转义了会产生什么效果? 10 ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list 11 # 错误: 因为前3个路径被合并成一个参数传递给了'ls -l' 12 # 而且两个经过转义的空格组织了参数(单词)分割. </PRE></FONT></TD></TR></TABLE></P><P> <SPANCLASS="TOKEN">转义符</SPAN>也提供续行功能, 也就是编写多行命令的功能. 一般的, 每一个单独行都包含一个不同的命令, 但是每行结尾的<SPANCLASS="TOKEN">转义符</SPAN>都会<EM>转义换行符</EM>, 这样下一行会与上一行一起形成一个命令序列. </P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 (cd /source/directory && tar cf - . ) | \ 2 (cd /dest/directory && tar xpvf -) 3 # 重复Alan Cox的目录数拷贝命令, 4 # 但是分成两行是为了增加可读性. 5 6 # 也可以使用如下方式: 7 tar cf - -C /source/directory . | 8 tar xpvf - -C /dest/directory 9 # 察看下边的注意事项. 10 # (感谢, Stephane Chazelas.)</PRE></FONT></TD></TR></TABLE> <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>如果一个脚本以<SPANCLASS="TOKEN">|</SPAN>结束, 管道符, 那么就不用非的加上转义符<SPANCLASS="TOKEN">\</SPAN>了. 但是一个好的编程风格, 还是应该在行尾加上转义符. </P></TD></TR></TABLE></DIV></P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 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 31 32 # 由Stephane Chazelas所建议的用例.</PRE></FONT></TD></TR></TABLE></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="quotingvar.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="exit-status.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">引用变量</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="quoting.html"ACCESSKEY="U">上一级</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">退出和退出状态码</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?