internalvariables.html

来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 3,354 行 · 第 1/4 页

HTML
3,354
字号
></DT><DD><P>与<SPANCLASS="TOKEN">$*</SPAN>相同, 但是每个参数都是一个独立的引用字符串, 		  这就意味着, 参数是被完整传递的, 并没有被解释或扩展. 		  这也意味着, 参数列表中每个参数都被看作为单独的单词.	      </P><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>当然, <SPANCLASS="QUOTE">"<CODECLASS="VARNAME">$@</CODE>"</SPAN>应该被引用起来.</P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ARGLIST"></A><P><B>例子 9-6. <BCLASS="COMMAND">arglist</B>: 通过$*和$@列出所有的参数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# arglist.sh  3&nbsp;# 多使用几个参数来调用这个脚本, 比如"one two three".  4&nbsp;  5&nbsp;E_BADARGS=65  6&nbsp;  7&nbsp;if [ ! -n "$1" ]  8&nbsp;then  9&nbsp;  echo "Usage: `basename $0` argument1 argument2 etc." 10&nbsp;  exit $E_BADARGS 11&nbsp;fi   12&nbsp; 13&nbsp;echo 14&nbsp; 15&nbsp;index=1          # 起始计数. 16&nbsp; 17&nbsp;echo "Listing args with \"\$*\":" 18&nbsp;for arg in "$*"  # 如果"$*"不被""引用,那么将不能正常地工作. 19&nbsp;do 20&nbsp;  echo "Arg #$index = $arg" 21&nbsp;  let "index+=1" 22&nbsp;done             # $* 将所有的参数看成一个单词. 23&nbsp;echo "Entire arg list seen as single word." 24&nbsp; 25&nbsp;echo 26&nbsp; 27&nbsp;index=1          # 重置计数(译者注: 从1开始). 28&nbsp;                 # 如果你写这句会发生什么? 29&nbsp; 30&nbsp;echo "Listing args with \"\$@\":" 31&nbsp;for arg in "$@" 32&nbsp;do 33&nbsp;  echo "Arg #$index = $arg" 34&nbsp;  let "index+=1" 35&nbsp;done             # $@ 把每个参数都看成是单独的单词. 36&nbsp;echo "Arg list seen as separate words." 37&nbsp; 38&nbsp;echo 39&nbsp; 40&nbsp;index=1          # 重置计数(译者注: 从1开始). 41&nbsp; 42&nbsp;echo "Listing args with \$* (unquoted):" 43&nbsp;for arg in $* 44&nbsp;do 45&nbsp;  echo "Arg #$index = $arg" 46&nbsp;  let "index+=1" 47&nbsp;done             # 未引用的$*将会把参数看成单独的单词.  48&nbsp;echo "Arg list seen as separate words." 49&nbsp; 50&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P><BCLASS="COMMAND">shift</B>命令执行以后, 	      <CODECLASS="VARNAME">$@</CODE>将会保存命令行中剩余的参数,  	      但是没有之前的<CODECLASS="VARNAME">$1</CODE>,	      因为被丢弃了.	        <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 使用 ./scriptname 1 2 3 4 5 来调用这个脚本  3&nbsp;  4&nbsp;echo "$@"    # 1 2 3 4 5  5&nbsp;shift  6&nbsp;echo "$@"    # 2 3 4 5  7&nbsp;shift  8&nbsp;echo "$@"    # 3 4 5  9&nbsp; 10&nbsp;# 每次"shift"都会丢弃$1. 11&nbsp;# "$@" 将包含剩下的参数. </PRE></FONT></TD></TR></TABLE>            </P><P><CODECLASS="VARNAME">$@</CODE>也可以作为工具使用, 用来过滤传递给脚本的输入. 			<BCLASS="COMMAND">cat "$@"</B>结构既可以接受从<TTCLASS="FILENAME">stdin</TT>传递给脚本的输入, 	      也可以接受从参数中指定的文件中传递给脚本的输入. 参见<AHREF="textproc.html#ROT13">例子 12-21</A>和<AHREF="textproc.html#CRYPTOQUOTE">例子 12-22</A> .</P><DIVCLASS="CAUTION"><P></P><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/caution.gif"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><CODECLASS="VARNAME">$*</CODE>和<CODECLASS="VARNAME">$@</CODE>中的参数有时候会表现出不一致而且令人迷惑的行为, 	      这都依赖于<AHREF="internalvariables.html#IFSREF">$IFS</A>的设置. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="INCOMPAT"></A><P><B>例子 9-7. <CODECLASS="VARNAME">$*</CODE>和<CODECLASS="VARNAME">$@</CODE>的不一致的行为</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;#  内部Bash变量"$*"和"$@"的古怪行为,  4&nbsp;#+ 都依赖于它们是否被双引号引用起来.  5&nbsp;#  单词拆分与换行的不一致的处理.  6&nbsp;  7&nbsp;  8&nbsp;set -- "First one" "second" "third:one" "" "Fifth: :one"  9&nbsp;# 设置这个脚本的参数, $1, $2, 等等. 10&nbsp; 11&nbsp;echo 12&nbsp; 13&nbsp;echo 'IFS unchanged, using "$*"' 14&nbsp;c=0 15&nbsp;for i in "$*"               # 引用起来 16&nbsp;do echo "$((c+=1)): [$i]"   # 这行在下边每个例子中都一样. 17&nbsp;                            # 打印参数. 18&nbsp;done 19&nbsp;echo --- 20&nbsp; 21&nbsp;echo 'IFS unchanged, using $*' 22&nbsp;c=0 23&nbsp;for i in $*                 # 未引用 24&nbsp;do echo "$((c+=1)): [$i]" 25&nbsp;done 26&nbsp;echo --- 27&nbsp; 28&nbsp;echo 'IFS unchanged, using "$@"' 29&nbsp;c=0 30&nbsp;for i in "$@" 31&nbsp;do echo "$((c+=1)): [$i]" 32&nbsp;done 33&nbsp;echo --- 34&nbsp; 35&nbsp;echo 'IFS unchanged, using $@' 36&nbsp;c=0 37&nbsp;for i in $@ 38&nbsp;do echo "$((c+=1)): [$i]" 39&nbsp;done 40&nbsp;echo --- 41&nbsp; 42&nbsp;IFS=: 43&nbsp;echo 'IFS=":", using "$*"' 44&nbsp;c=0 45&nbsp;for i in "$*" 46&nbsp;do echo "$((c+=1)): [$i]" 47&nbsp;done 48&nbsp;echo --- 49&nbsp; 50&nbsp;echo 'IFS=":", using $*' 51&nbsp;c=0 52&nbsp;for i in $* 53&nbsp;do echo "$((c+=1)): [$i]" 54&nbsp;done 55&nbsp;echo --- 56&nbsp; 57&nbsp;var=$* 58&nbsp;echo 'IFS=":", using "$var" (var=$*)' 59&nbsp;c=0 60&nbsp;for i in "$var" 61&nbsp;do echo "$((c+=1)): [$i]" 62&nbsp;done 63&nbsp;echo --- 64&nbsp; 65&nbsp;echo 'IFS=":", using $var (var=$*)' 66&nbsp;c=0 67&nbsp;for i in $var 68&nbsp;do echo "$((c+=1)): [$i]" 69&nbsp;done 70&nbsp;echo --- 71&nbsp; 72&nbsp;var="$*" 73&nbsp;echo 'IFS=":", using $var (var="$*")' 74&nbsp;c=0 75&nbsp;for i in $var 76&nbsp;do echo "$((c+=1)): [$i]" 77&nbsp;done 78&nbsp;echo --- 79&nbsp; 80&nbsp;echo 'IFS=":", using "$var" (var="$*")' 81&nbsp;c=0 82&nbsp;for i in "$var" 83&nbsp;do echo "$((c+=1)): [$i]" 84&nbsp;done 85&nbsp;echo --- 86&nbsp; 87&nbsp;echo 'IFS=":", using "$@"' 88&nbsp;c=0 89&nbsp;for i in "$@" 90&nbsp;do echo "$((c+=1)): [$i]" 91&nbsp;done 92&nbsp;echo --- 93&nbsp; 94&nbsp;echo 'IFS=":", using $@' 95&nbsp;c=0 96&nbsp;for i in $@ 97&nbsp;do echo "$((c+=1)): [$i]" 98&nbsp;done 99&nbsp;echo ---100&nbsp;101&nbsp;var=$@102&nbsp;echo 'IFS=":", using $var (var=$@)'103&nbsp;c=0104&nbsp;for i in $var105&nbsp;do echo "$((c+=1)): [$i]"106&nbsp;done107&nbsp;echo ---108&nbsp;109&nbsp;echo 'IFS=":", using "$var" (var=$@)'110&nbsp;c=0111&nbsp;for i in "$var"112&nbsp;do echo "$((c+=1)): [$i]"113&nbsp;done114&nbsp;echo ---115&nbsp;116&nbsp;var="$@"117&nbsp;echo 'IFS=":", using "$var" (var="$@")'118&nbsp;c=0119&nbsp;for i in "$var"120&nbsp;do echo "$((c+=1)): [$i]"121&nbsp;done122&nbsp;echo ---123&nbsp;124&nbsp;echo 'IFS=":", using $var (var="$@")'125&nbsp;c=0126&nbsp;for i in $var127&nbsp;do echo "$((c+=1)): [$i]"128&nbsp;done129&nbsp;130&nbsp;echo131&nbsp;132&nbsp;# 使用ksh或者zsh -y来试试这个脚本.133&nbsp;134&nbsp;exit 0135&nbsp;136&nbsp;# 这个例子脚本是由Stephane Chazelas所编写,137&nbsp;# 并且本书作者做了轻微改动.</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="NOTE"><P></P><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/note.gif"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><BCLASS="COMMAND">$@</B>与<BCLASS="COMMAND">$*</B>中的参数只有在被双引号引用起来的时候才会不同. </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="IFSEMPTY"></A><P><B>例子 9-8. 当<CODECLASS="VARNAME">$IFS</CODE>为空时的<CODECLASS="VARNAME">$*</CODE>和<CODECLASS="VARNAME">$@</CODE></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;#  如果$IFS被设置, 但其值为空,  4&nbsp;#+ 那么"$*"和"$@"将不会像期望的那样显示位置参数.   5&nbsp;  6&nbsp;mecho ()       # 打印位置参数.  7&nbsp;{  8&nbsp;echo "$1,$2,$3";  9&nbsp;} 10&nbsp; 11&nbsp; 12&nbsp;IFS=""         # 设置了, 但值为空. 13&nbsp;set a b c      # 位置参数. 14&nbsp; 15&nbsp;mecho "$*"     # abc,, 16&nbsp;mecho $*       # a,b,c 17&nbsp; 18&nbsp;mecho $@       # a,b,c 19&nbsp;mecho "$@"     # a,b,c 20&nbsp; 21&nbsp;#  当$IFS值为空时, $*和$@的行为依赖于 22&nbsp;#+ 正在运行的Bash或者sh的版本. 23&nbsp;#  因此在脚本中使用这种"特性"是不明智的. 24&nbsp; 25&nbsp; 26&nbsp;# 感谢, Stephane Chazelas. 27&nbsp; 28&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV></DD></DL></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B>其他的特殊参数</B></P><DL><DT><ANAME="FLPREF"></A><CODECLASS="VARNAME">$-</CODE></DT><DD><P>传递给脚本的标记(使用<AHREF="internal.html#SETREF">set</A>命令). 参见<AHREF="internal.html#EX34">例子 11-15</A>.</P><DIVCLASS="CAUTION"><P></P><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/caution.gif"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>这本来是<EM>ksh</EM>的结构, 后来被引进到Bash中, 但是不幸的是, 				看起来它不能够可靠的用在Bash脚本中. 一种可能的用法是让一个脚本<AHREF="intandnonint.html#IITEST">测试自身是不是可交互的</A>. </P></TD></TR></TABLE></DIV></DD><DT><CODECLASS="VARNAME">$!</CODE></DT><DD><P>运行在后台的最后一个作业的PID(进程ID)</P><P>	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;LOG=$0.log  2&nbsp;  3&nbsp;COMMAND1="sleep 100"  4&nbsp;  5&nbsp;echo "Logging PIDs background commands for script: $0" &#62;&#62; "$LOG"  6&nbsp;# 所以它们是可以被监控的, 并且可以在必要的时候kill掉它们.  7&nbsp;echo &#62;&#62; "$LOG"  8&nbsp;  9&nbsp;# 记录命令. 10&nbsp; 11&nbsp;echo -n "PID of \"$COMMAND1\":  " &#62;&#62; "$LOG" 12&nbsp;${COMMAND1} &#38; 13&nbsp;echo $! &#62;&#62; "$LOG" 14&nbsp;# "sleep 100"的PID:  1506 15&nbsp; 16&nbsp;# 感谢, Jacques Lederer, 对此的建议.</PRE></FONT></TD></TR></TABLE>            </P><P>	      <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;possibly_hanging_job &#38; { sleep ${TIMEOUT}; eval 'kill -9 $!' &#38;&#62; /dev/null; }  2&nbsp;# 强制结束一个出错程序.  3&nbsp;# 很有用, 比如用在init脚本中.  4&nbsp;  5&nbsp;# 感谢, Sylvain Fourmanoit, 发现了"!"变量的创造性用法.</PRE></FONT></TD></TR></TABLE>            </P></DD><DT><ANAME="UNDERSCOREREF"></A><CODECLASS="VARNAME">$_</CODE></DT><DD><P>这个变量保存之前执行的命令的最后一个参数的值. </P><DIVCLASS="EXAMPLE"><HR><ANAME="USCREF"></A><P><B>例子 9-9. 下划线变量</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;echo $_              # /bin/bash  4&nbsp;                     # 只是调用/bin/bash来运行这个脚本.  5&nbsp;  6&nbsp;du &#62;/dev/null        # 这么做命令行上将没有输出.  7&nbsp;echo $_              # du  8&nbsp;  9&nbsp;ls -al &#62;/dev/null    # 这么做命令行上将没有输出. 10&nbsp;echo $_              # -al  (这是最后的参数) 11&nbsp; 12&nbsp;: 13&nbsp;echo $_              # :</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><ANAME="XSTATVARREF"></A><CODECLASS="VARNAME">$?</CODE></DT><DD><P>命令, <AHREF="functions.html#FUNCTIONREF">函数</A>,	    或者是脚本本身的(参见<AHREF="complexfunct.html#MAX">例子 23-7</A>)<AHREF="exit-status.html#EXITSTATUSREF">退出状态码</A></P></DD><DT><ANAME="PROCCID"></A><CODECLASS="VARNAME">$$</CODE></DT><DD><P>脚本自身的进程ID. 			  <CODECLASS="VARNAME">$$</CODE>变量在脚本中经常用来构造<SPANCLASS="QUOTE">"唯一的"</SPAN>临时文件名(参见<AHREF="contributed-scripts.html#FTPGET">例子 A-13</A>, 				  <AHREF="debugging.html#ONLINE">例子 29-6</A>, <AHREF="filearchiv.html#DERPM">例子 12-28</A>, 和<AHREF="x6756.html#SELFDESTRUCT">例子 11-26</A>). 这么做通常比调用<AHREF="filearchiv.html#MKTEMPREF">mktemp</A>命令来的简单.</P></DD></DL></DIV></DIV><H3CLASS="FOOTNOTES">注意事项</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN4091"HREF="internalvariables.html#AEN4091"><SPANCLASS="footnote">[1]</SPAN></A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>当然, 当前运行脚本的PID就是<CODECLASS="VARNAME">$$</CODE></P></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN4390"HREF="internalvariables.html#AEN4390"><SPANCLASS="footnote">[2]</SPAN></A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>术语<SPANCLASS="QUOTE">"argument"</SPAN>和<SPANCLASS="QUOTE">"parameter"</SPAN>通常情况下都可以互换使用. 				在本书的上下文中, 它们的意思完全相同, 意思都是传递给脚本或者函数的变量, 或者是位置参数. 		(译者注: 翻译时, 基本上就未加区分.)</P></TD></TR></TABLE><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="variables2.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="string-manipulation.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">变量重游</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="variables2.html"ACCESSKEY="U">上一级</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">操作字符串</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

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