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 #!/bin/bash 2 # arglist.sh 3 # 多使用几个参数来调用这个脚本, 比如"one two three". 4 5 E_BADARGS=65 6 7 if [ ! -n "$1" ] 8 then 9 echo "Usage: `basename $0` argument1 argument2 etc." 10 exit $E_BADARGS 11 fi 12 13 echo 14 15 index=1 # 起始计数. 16 17 echo "Listing args with \"\$*\":" 18 for arg in "$*" # 如果"$*"不被""引用,那么将不能正常地工作. 19 do 20 echo "Arg #$index = $arg" 21 let "index+=1" 22 done # $* 将所有的参数看成一个单词. 23 echo "Entire arg list seen as single word." 24 25 echo 26 27 index=1 # 重置计数(译者注: 从1开始). 28 # 如果你写这句会发生什么? 29 30 echo "Listing args with \"\$@\":" 31 for arg in "$@" 32 do 33 echo "Arg #$index = $arg" 34 let "index+=1" 35 done # $@ 把每个参数都看成是单独的单词. 36 echo "Arg list seen as separate words." 37 38 echo 39 40 index=1 # 重置计数(译者注: 从1开始). 41 42 echo "Listing args with \$* (unquoted):" 43 for arg in $* 44 do 45 echo "Arg #$index = $arg" 46 let "index+=1" 47 done # 未引用的$*将会把参数看成单独的单词. 48 echo "Arg list seen as separate words." 49 50 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 #!/bin/bash 2 # 使用 ./scriptname 1 2 3 4 5 来调用这个脚本 3 4 echo "$@" # 1 2 3 4 5 5 shift 6 echo "$@" # 2 3 4 5 7 shift 8 echo "$@" # 3 4 5 9 10 # 每次"shift"都会丢弃$1. 11 # "$@" 将包含剩下的参数. </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 #!/bin/bash 2 3 # 内部Bash变量"$*"和"$@"的古怪行为, 4 #+ 都依赖于它们是否被双引号引用起来. 5 # 单词拆分与换行的不一致的处理. 6 7 8 set -- "First one" "second" "third:one" "" "Fifth: :one" 9 # 设置这个脚本的参数, $1, $2, 等等. 10 11 echo 12 13 echo 'IFS unchanged, using "$*"' 14 c=0 15 for i in "$*" # 引用起来 16 do echo "$((c+=1)): [$i]" # 这行在下边每个例子中都一样. 17 # 打印参数. 18 done 19 echo --- 20 21 echo 'IFS unchanged, using $*' 22 c=0 23 for i in $* # 未引用 24 do echo "$((c+=1)): [$i]" 25 done 26 echo --- 27 28 echo 'IFS unchanged, using "$@"' 29 c=0 30 for i in "$@" 31 do echo "$((c+=1)): [$i]" 32 done 33 echo --- 34 35 echo 'IFS unchanged, using $@' 36 c=0 37 for i in $@ 38 do echo "$((c+=1)): [$i]" 39 done 40 echo --- 41 42 IFS=: 43 echo 'IFS=":", using "$*"' 44 c=0 45 for i in "$*" 46 do echo "$((c+=1)): [$i]" 47 done 48 echo --- 49 50 echo 'IFS=":", using $*' 51 c=0 52 for i in $* 53 do echo "$((c+=1)): [$i]" 54 done 55 echo --- 56 57 var=$* 58 echo 'IFS=":", using "$var" (var=$*)' 59 c=0 60 for i in "$var" 61 do echo "$((c+=1)): [$i]" 62 done 63 echo --- 64 65 echo 'IFS=":", using $var (var=$*)' 66 c=0 67 for i in $var 68 do echo "$((c+=1)): [$i]" 69 done 70 echo --- 71 72 var="$*" 73 echo 'IFS=":", using $var (var="$*")' 74 c=0 75 for i in $var 76 do echo "$((c+=1)): [$i]" 77 done 78 echo --- 79 80 echo 'IFS=":", using "$var" (var="$*")' 81 c=0 82 for i in "$var" 83 do echo "$((c+=1)): [$i]" 84 done 85 echo --- 86 87 echo 'IFS=":", using "$@"' 88 c=0 89 for i in "$@" 90 do echo "$((c+=1)): [$i]" 91 done 92 echo --- 93 94 echo 'IFS=":", using $@' 95 c=0 96 for i in $@ 97 do echo "$((c+=1)): [$i]" 98 done 99 echo ---100 101 var=$@102 echo 'IFS=":", using $var (var=$@)'103 c=0104 for i in $var105 do echo "$((c+=1)): [$i]"106 done107 echo ---108 109 echo 'IFS=":", using "$var" (var=$@)'110 c=0111 for i in "$var"112 do echo "$((c+=1)): [$i]"113 done114 echo ---115 116 var="$@"117 echo 'IFS=":", using "$var" (var="$@")'118 c=0119 for i in "$var"120 do echo "$((c+=1)): [$i]"121 done122 echo ---123 124 echo 'IFS=":", using $var (var="$@")'125 c=0126 for i in $var127 do echo "$((c+=1)): [$i]"128 done129 130 echo131 132 # 使用ksh或者zsh -y来试试这个脚本.133 134 exit 0135 136 # 这个例子脚本是由Stephane Chazelas所编写,137 # 并且本书作者做了轻微改动.</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 #!/bin/bash 2 3 # 如果$IFS被设置, 但其值为空, 4 #+ 那么"$*"和"$@"将不会像期望的那样显示位置参数. 5 6 mecho () # 打印位置参数. 7 { 8 echo "$1,$2,$3"; 9 } 10 11 12 IFS="" # 设置了, 但值为空. 13 set a b c # 位置参数. 14 15 mecho "$*" # abc,, 16 mecho $* # a,b,c 17 18 mecho $@ # a,b,c 19 mecho "$@" # a,b,c 20 21 # 当$IFS值为空时, $*和$@的行为依赖于 22 #+ 正在运行的Bash或者sh的版本. 23 # 因此在脚本中使用这种"特性"是不明智的. 24 25 26 # 感谢, Stephane Chazelas. 27 28 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 LOG=$0.log 2 3 COMMAND1="sleep 100" 4 5 echo "Logging PIDs background commands for script: $0" >> "$LOG" 6 # 所以它们是可以被监控的, 并且可以在必要的时候kill掉它们. 7 echo >> "$LOG" 8 9 # 记录命令. 10 11 echo -n "PID of \"$COMMAND1\": " >> "$LOG" 12 ${COMMAND1} & 13 echo $! >> "$LOG" 14 # "sleep 100"的PID: 1506 15 16 # 感谢, Jacques Lederer, 对此的建议.</PRE></FONT></TD></TR></TABLE> </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 possibly_hanging_job & { sleep ${TIMEOUT}; eval 'kill -9 $!' &> /dev/null; } 2 # 强制结束一个出错程序. 3 # 很有用, 比如用在init脚本中. 4 5 # 感谢, 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 #!/bin/bash 2 3 echo $_ # /bin/bash 4 # 只是调用/bin/bash来运行这个脚本. 5 6 du >/dev/null # 这么做命令行上将没有输出. 7 echo $_ # du 8 9 ls -al >/dev/null # 这么做命令行上将没有输出. 10 echo $_ # -al (这是最后的参数) 11 12 : 13 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 + -
显示快捷键?