internal.html

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

HTML
3,324
字号
></TR></TABLE>	      </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX43"></A><P><B>例子 11-11. 展示<BCLASS="COMMAND">eval</B>命令的效果</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;y=`eval ls -l`  #  与 y=`ls -l` 很相似  4&nbsp;echo $y         #+ 但是换行符将会被删除, 因为"echo"的变量未被""引用.  5&nbsp;echo  6&nbsp;echo "$y"       #  用""将变量引用起来, 换行符就不会被空格替换了.  7&nbsp;  8&nbsp;echo; echo  9&nbsp; 10&nbsp;y=`eval df`     #  与 y=`df` 很相似 11&nbsp;echo $y         #+ 换行符又被空格替换了. 12&nbsp; 13&nbsp;#  当没有LF(换行符)出现时, 如果使用"awk"这样的工具来分析输出的结果,  14&nbsp;#+ 应该能更容易一些. 15&nbsp; 16&nbsp;echo 17&nbsp;echo "===========================================================" 18&nbsp;echo 19&nbsp; 20&nbsp;# 现在,来看一下怎么用"eval"命令来"扩展"一个变量 . . . 21&nbsp; 22&nbsp;for i in 1 2 3 4 5; do 23&nbsp;  eval value=$i 24&nbsp;  #  value=$i 具有相同的效果, 在这里并不是非要使用"eval"不可.  25&nbsp;  #  一个缺乏特殊含义的变量将被评价为自身 -- 也就是说, 26&nbsp;  #+ 这个变量除了能够被扩展成自身所表示的字符外, 不能被扩展成任何其他的含义. 27&nbsp;  echo $value 28&nbsp;done 29&nbsp; 30&nbsp;echo 31&nbsp;echo "---" 32&nbsp;echo 33&nbsp; 34&nbsp;for i in ls df; do 35&nbsp;  value=eval $i 36&nbsp;  #  value=$i 在这里就与上边这句有了本质上的区别. 37&nbsp;  #  "eval" 将会评价命令 "ls" 和 "df" . . . 38&nbsp;  #  术语 "ls" 和 "df" 就具有特殊含义, 39&nbsp;  #+ 因为它们被解释成命令, 40&nbsp;  #+ 而不是字符串本身. 41&nbsp;  echo $value 42&nbsp;done 43&nbsp; 44&nbsp; 45&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX44"></A><P><B>例子 11-12. 强制登出(log-off)</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 结束ppp进程来强制登出log-off.  3&nbsp;  4&nbsp;# 本脚本应该以root用户的身份来运行.  5&nbsp;  6&nbsp;killppp="eval kill -9 `ps ax | awk '/ppp/ { print $1 }'`"  7&nbsp;#                     -------- ppp的进程ID -------    8&nbsp;  9&nbsp;$killppp                  # 这个变量现在成为了一个命令. 10&nbsp; 11&nbsp; 12&nbsp;# 下边的命令必须以root用户的身份来运行. 13&nbsp; 14&nbsp;chmod 666 /dev/ttyS3      # 恢复读写权限,否则什么? 15&nbsp;#  因为在ppp上执行一个SIGKILL将会修改串口的权限, 16&nbsp;#+ 我们把权限恢复到之前的状态. 17&nbsp; 18&nbsp;rm /var/lock/LCK..ttyS3   # 删除串口琐文件.为什么? 19&nbsp; 20&nbsp;exit 0 21&nbsp; 22&nbsp;# 练习: 23&nbsp;# ----- 24&nbsp;# 1) 编写一个脚本来验证是否root用户正在运行它. 25&nbsp;# 2) 做一个检查, 在杀掉某个进程之前,  26&nbsp;#+   检查一下这个将要被杀掉的进程是否正在运行. 27&nbsp;# 3) 基于'fuser'来编写达到这个目的的另一个版本的脚本 28&nbsp;#+      if [ fuser -s /dev/modem ]; then . . .</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ROT14"></A><P><B>例子 11-13. 另一个<SPANCLASS="QUOTE">"rot13"</SPAN>版本</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 使用'eval'的一个"rot13"的版本,(译者:rot13就是把26个字母,从中间分为2半,各13个).  3&nbsp;# 与脚本"rot13.sh" 比较一下.  4&nbsp;  5&nbsp;setvar_rot_13()              # "rot13" 函数  6&nbsp;{  7&nbsp;  local varname=$1 varvalue=$2  8&nbsp;  eval $varname='$(echo "$varvalue" | tr a-z n-za-m)'  9&nbsp;} 10&nbsp; 11&nbsp; 12&nbsp;setvar_rot_13 var "foobar"   # 将 "foobar" 传递到 rot13函数中. 13&nbsp;echo $var                    # sbbone 14&nbsp; 15&nbsp;setvar_rot_13 var "$var"     # 传递 "sbbone" 到rot13函数中. 16&nbsp;                             # 又变成了原始值. 17&nbsp;echo $var                    # foobar 18&nbsp; 19&nbsp;# 这个例子是Segebart Chazelas编写的. 20&nbsp;# 作者又修改了一下. 21&nbsp; 22&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>Rory Winston 捐献了下边的脚本, 			关于使用<BCLASS="COMMAND">eval</B>命令. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EVALEX"></A><P><B>例子 11-14. 在Perl脚本中使用<BCLASS="COMMAND">eval</B>命令来强制变量替换</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;In the Perl script "test.pl":  2&nbsp;        ...		  3&nbsp;        my $WEBROOT = &#60;WEBROOT_PATH&#62;;  4&nbsp;        ...  5&nbsp;  6&nbsp;To force variable substitution try:  7&nbsp;        $export WEBROOT_PATH=/usr/local/webroot  8&nbsp;        $sed 's/&#60;WEBROOT_PATH&#62;/$WEBROOT_PATH/' &#60; test.pl &#62; out  9&nbsp; 10&nbsp;But this just gives: 11&nbsp;        my $WEBROOT = $WEBROOT_PATH; 12&nbsp; 13&nbsp;However: 14&nbsp;        $export WEBROOT_PATH=/usr/local/webroot 15&nbsp;        $eval sed 's%\&#60;WEBROOT_PATH\&#62;%$WEBROOT_PATH%' &#60; test.pl &#62; out 16&nbsp;#        ==== 17&nbsp; 18&nbsp;That works fine, and gives the expected substitution: 19&nbsp;        my $WEBROOT = /usr/local/webroot; 20&nbsp; 21&nbsp; 22&nbsp;### Paulo Marcel Coelho Aragao校正了这个原始例子.</PRE></FONT></TD></TR></TABLE><HR></DIV><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><BCLASS="COMMAND">eval</B>命令是有风险的,				如果你有更合适的方法来实现功能的话, 				尽量避免使用它.				<KBDCLASS="USERINPUT">eval $COMMANDS</KBD>将会执行命令<TTCLASS="REPLACEABLE"><I>COMMANDS</I></TT>的内容, 				如果命令中包含有<BCLASS="COMMAND">rm -rf *</B>这样的东西, 可能就不是你想要的了. 				当你运行一个包含有<BCLASS="COMMAND">eval</B>命令的陌生人所编写的代码片段的时候, 这是一件很危险的事情. 		</P></TD></TR></TABLE></DIV></DD><DT><ANAME="SETREF"></A><BCLASS="COMMAND">set</B></DT><DD><P><BCLASS="COMMAND">set</B>命令用来修改内部脚本变量的值. 	      它的一个作用就是触发<AHREF="options.html#OPTIONSREF">选项标志位</A>来帮助决定脚本的行为. 	      另一个作用是以一个命令的结果(<KBDCLASS="USERINPUT">set	      `command`</KBD>)来重新设置脚本的<AHREF="internalvariables.html#POSPARAMREF">位置参数</A>. 	  脚本将会从命令的输出中重新分析出位置参数. 		  </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX34"></A><P><B>例子 11-15. 使用<BCLASS="COMMAND">set</B>命令来改变脚本的位置参数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;# script "set-test"  4&nbsp;  5&nbsp;# 使用3个命令行参数来调用这个脚本,  6&nbsp;# 比如, "./set-test one two three".  7&nbsp;  8&nbsp;echo  9&nbsp;echo "Positional parameters before  set \`uname -a\` :" 10&nbsp;echo "Command-line argument #1 = $1" 11&nbsp;echo "Command-line argument #2 = $2" 12&nbsp;echo "Command-line argument #3 = $3" 13&nbsp; 14&nbsp; 15&nbsp;set `uname -a` # 把`uname -a`的命令输出设置 16&nbsp;               # 为新的位置参数. 17&nbsp; 18&nbsp;echo $_        # unknown(译者注: 这要看你的uname -a输出了,这句打印出的就是输出的最后一个单词.) 19&nbsp;# 在脚本中设置标志. 20&nbsp; 21&nbsp;echo "Positional parameters after  set \`uname -a\` :" 22&nbsp;# $1, $2, $3, 等等. 这些位置参数将被重新初始化为`uname -a`的结果 23&nbsp;echo "Field #1 of 'uname -a' = $1" 24&nbsp;echo "Field #2 of 'uname -a' = $2" 25&nbsp;echo "Field #3 of 'uname -a' = $3" 26&nbsp;echo --- 27&nbsp;echo $_        # --- 28&nbsp;echo 29&nbsp; 30&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>关于位置参数更多有趣的事情.</P><DIVCLASS="EXAMPLE"><HR><ANAME="REVPOSPARAMS"></A><P><B>例子 11-16. 反转位置参数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# revposparams.sh: 反转位置参数.  3&nbsp;# 本脚本由Dan Jacobson所编写, 本书作者做了一些格式上的修正.  4&nbsp;  5&nbsp;  6&nbsp;set a\ b c d\ e;  7&nbsp;#     ^      ^     转义的空格  8&nbsp;#       ^ ^        未转义的空格  9&nbsp;OIFS=$IFS; IFS=:; 10&nbsp;#              ^   保存旧的IFS, 然后设置新的IFS. 11&nbsp; 12&nbsp;echo 13&nbsp; 14&nbsp;until [ $# -eq 0 ] 15&nbsp;do          #      步进位置参数. 16&nbsp;  echo "### k0 = "$k""     # 步进之前 17&nbsp;  k=$1:$k;  #      将每个位置参数都附加在循环变量的后边. 18&nbsp;#     ^ 19&nbsp;  echo "### k = "$k""      # 步进之后 20&nbsp;  echo 21&nbsp;  shift; 22&nbsp;done 23&nbsp; 24&nbsp;set $k  #  设置一个新的位置参数. 25&nbsp;echo - 26&nbsp;echo $# #  察看位置参数的个数. 27&nbsp;echo - 28&nbsp;echo 29&nbsp; 30&nbsp;for i   #  省略 "in list" 结构,  31&nbsp;        #+ 为位置参数设置变量 -- i --. 32&nbsp;do 33&nbsp;  echo $i  # 显示新的位置参数. 34&nbsp;done 35&nbsp; 36&nbsp;IFS=$OIFS  # 恢复 IFS. 37&nbsp; 38&nbsp;#  问题: 39&nbsp;#  是否有必要设置新的IFS, 内部域分隔符, 40&nbsp;#+ 才能够让这个脚本正常运行? (译者注: 当然有必要.) 41&nbsp;#  如果你没设置新的IFS, 会发生什么? 试一下. 42&nbsp;#  并且, 在第17行, 为什么新的IFS要使用 -- 一个冒号 -- , 43&nbsp;#+ 来将位置参数附加到循环变量中? 44&nbsp;#  这么做的目的是什么? 45&nbsp; 46&nbsp;exit 0 47&nbsp; 48&nbsp;$ ./revposparams.sh 49&nbsp; 50&nbsp;### k0 =  51&nbsp;### k = a b 52&nbsp; 53&nbsp;### k0 = a b 54&nbsp;### k = c a b 55&nbsp; 56&nbsp;### k0 = c a b 57&nbsp;### k = d e c a b 58&nbsp; 59&nbsp;- 60&nbsp;3 61&nbsp;- 62&nbsp; 63&nbsp;d e 64&nbsp;c 65&nbsp;a b</PRE></FONT></TD></TR></TABLE><HR></DIV><P>不使用任何选项或参数来调用<BCLASS="COMMAND">set</B>命令的话, 	      将会列出所有的<AHREF="othertypesv.html#ENVREF">环境变量</A>和其他所有的已经初始化过的变量.	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">set</KBD><SAMPCLASS="COMPUTEROUTPUT">AUTHORCOPY=/home/bozo/posts BASH=/bin/bash BASH_VERSION=$'2.05.8(1)-release' ... XAUTHORITY=/home/bozo/.Xauthority _=/etc/bashrc variable22=abc variable23=xzy</SAMP>	      </PRE></FONT></TD></TR></TABLE>            </P><P>如果使用参数<CODECLASS="OPTION">--</CODE>来调用<BCLASS="COMMAND">set</B>命令的话, 	      将会明确的分配位置参数.		  如果<CODECLASS="OPTION">--</CODE>选项后边没有跟变量名的话, 		  那么结果就使得所有位置参数都被<EM>unsets</EM>了.	      </P><DIVCLASS="EXAMPLE"><HR><ANAME="SETPOS"></A><P><B>例子 11-17. 重新分配位置参数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;variable="one two three four five"  4&nbsp;  5&nbsp;set -- $variable  6&nbsp;# 将位置参数的内容设为变量"$variable"的内容.  7&nbsp;  8&nbsp;first_param=$1  9&nbsp;second_param=$2 10&nbsp;shift; shift        # 将最前面的两个位置参数移除. 11&nbsp;remaining_params="$*" 12&nbsp; 13&nbsp;echo 14&nbsp;echo "first parameter = $first_param"             # one 15&nbsp;echo "second parameter = $second_param"           # two 16&nbsp;echo "remaining parameters = $remaining_params"   # three four five 17&nbsp; 18&nbsp;echo; echo 19&nbsp; 20&nbsp;# 再来一次. 21&nbsp;set -- $variable 22&nbsp;first_param=$1 23&nbsp;second_param=$2 24&nbsp;echo "first parameter = $first_param"             # one 25&nbsp;echo "second parameter = $second_param"           # two 26&nbsp; 27&nbsp;# ====================================================== 28&nbsp; 29&nbsp;set -- 30&nbsp;# 如果没指定变量,那么将会unset所有的位置参数. 31&nbsp; 32&nbsp;first_param=$1 33&nbsp;second_param=$2 34&nbsp;echo "first parameter = $first_param"             # (null value) 35&nbsp;echo "second parameter = $second_param"           # (null value) 36&nbsp; 37&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>参考<AHREF="loops1.html#EX22A">例子 10-2</A>和<AHREF="extmisc.html#EX33A">例子 12-51</A>.</P></DD><DT><ANAME="UNSETREF"></A><BCLASS="COMMAND">unset</B></DT><DD><P><BCLASS="COMMAND">unset</B>命令用来删除一个shell变量, 			  这个命令的效果就是把这个变量设为<EM>null</EM>. 			  注意: 这个命令对位置参数无效. </P><P>	      <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">unset PATH</KBD><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">echo $PATH</KBD><SAMPCLASS="COMPUTEROUTPUT">&#13;</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP></PRE></FONT></TD></TR></TABLE>	    </P><DIVCLASS="EXAMPLE"><HR><ANAME="UNS"></A><P><B>例子 11-18. <SPANCLASS="QUOTE">"Unsett"</SPAN>一个变量</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD

⌨️ 快捷键说明

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