internal.html

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

HTML
3,324
字号
><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# unset.sh: Unset 一个变量.  3&nbsp;  4&nbsp;variable=hello                       # 初始化.  5&nbsp;echo "variable = $variable"  6&nbsp;  7&nbsp;unset variable                       # Unset.  8&nbsp;                                     # 与 variable= 效果相同.  9&nbsp;echo "(unset) variable = $variable"  # $variable 设为 null. 10&nbsp; 11&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><ANAME="EXPORTREF"></A><BCLASS="COMMAND">export</B></DT><DD><P><BCLASS="COMMAND">export</B>命令将会使得被export的变量在所运行脚本(或shell)的所有子进程中都可用. 			  <EM>不幸的是, 没有办法</EM>将<EM>变量</EM>export<EM>到父进程中, 				  这里所指的父进程就是调用这个脚本的脚本或shell.</EM> 	      关于<BCLASS="COMMAND">export</B>命令的一个重要的用法就是使用在<AHREF="files.html#FILESREF1">启动文件</A>中, 		  启动文件用来初始化和设置<AHREF="othertypesv.html#ENVREF">环境变量</A>, 		  这样, 用户进程才能够访问环境变量. </P><DIVCLASS="EXAMPLE"><HR><ANAME="COLTOTALER3"></A><P><B>例子 11-19. 使用<BCLASS="COMMAND">export</B>命令来将一个变量传递到一个内嵌<AHREF="awk.html#AWKREF">awk</A>的脚本中</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;#  这是"求列的和"脚本的另外一个版本(col-totaler.sh)  4&nbsp;#+ 那个脚本可以把目标文件中的指定的列上的所有数字全部累加起来,求和.  5&nbsp;#  这个版本将把一个变量通过export的形式传递到'awk'中 . . .  6&nbsp;#+ 并且把awk脚本放到一个变量中.  7&nbsp;  8&nbsp;  9&nbsp;ARGS=2 10&nbsp;E_WRONGARGS=65 11&nbsp; 12&nbsp;if [ $# -ne "$ARGS" ] # 检查命令行参数的个数. 13&nbsp;then 14&nbsp;   echo "Usage: `basename $0` filename column-number" 15&nbsp;   exit $E_WRONGARGS 16&nbsp;fi 17&nbsp; 18&nbsp;filename=$1 19&nbsp;column_number=$2 20&nbsp; 21&nbsp;#===== 上边的这部分,与原始脚本完全一样 =====# 22&nbsp; 23&nbsp;export column_number 24&nbsp;# 将列号export出来, 这样后边的进程就可用了. 25&nbsp; 26&nbsp; 27&nbsp;# ----------------------------------------------- 28&nbsp;awkscript='{ total += $ENVIRON["column_number"] } 29&nbsp;END { print total }' 30&nbsp;# 是的, 变量可以保存awk脚本. 31&nbsp;# ----------------------------------------------- 32&nbsp; 33&nbsp;# 现在, 运行这个awk脚本. 34&nbsp;awk "$awkscript" "$filename" 35&nbsp; 36&nbsp;# 感谢, Stephane Chazelas. 37&nbsp; 38&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="TIP"><P></P><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/tip.gif"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>可以在一个操作中同时进行赋值和export变量, 比如: 				  <BCLASS="COMMAND">export var1=xxx</B>.</P><P>然而, 就像Greg Keraunen所指出的, 				  在某些情况下, 如果使用上边这种形式的话, 		  将与先设置变量, 然后export变量效果不同. </P><P>	        <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">export var=(a b); echo ${var[0]}</KBD><SAMPCLASS="COMPUTEROUTPUT">(a b)</SAMP><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">var=(a b); export var; echo ${var[0]}</KBD><SAMPCLASS="COMPUTEROUTPUT">a</SAMP>	      </PRE></FONT></TD></TR></TABLE>	    </P></TD></TR></TABLE></DIV></DD><DT><BCLASS="COMMAND">declare</B>, <BCLASS="COMMAND">typeset</B></DT><DD><P><AHREF="declareref.html">declare</A>和<AHREF="declareref.html">typeset</A>命令被用来指定或限制变量的属性. </P></DD><DT><BCLASS="COMMAND">readonly</B></DT><DD><P>与<AHREF="declareref.html">declare -r</A>作用相同,	      设置变量的只读属性, 或者可以认为这个变量就是一个常量.	      设置了这种属性之后, 如果你还要修改它, 那么将会得到一个错误信息.	      这种情况与<EM>C</EM>语言中的<BCLASS="COMMAND">const</B>常量类型是相同的.	      </P></DD><DT><ANAME="GETOPTSX"></A><BCLASS="COMMAND">getopts</B></DT><DD><P>可以说这个命令是分析传递到脚本中命令行参数的最强力的工具.	      这个命令与外部命令<AHREF="extmisc.html#GETOPTY">getopt</A>, 		  还有<EM>C</EM>语言中的库函数<BCLASS="COMMAND">getopt</B>的作用是相同的. 	       它允许传递和连接多个选项		   <ANAME="AEN6448"HREF="#FTN.AEN6448"><SPANCLASS="footnote">[2]</SPAN></A>	      到脚本中, 并且能够分配多个参数到脚本中(比如: <KBDCLASS="USERINPUT">scriptname -abc -e /usr/local</KBD>).</P><P><BCLASS="COMMAND">getopts</B>结构使用两个隐含变量. 	      <CODECLASS="VARNAME">$OPTIND</CODE>是参数指针(<ICLASS="WORDASWORD">选项索引</I>)	      和<CODECLASS="VARNAME">$OPTARG</CODE>(<ICLASS="WORDASWORD">选项参数</I>)(可选的)可以在选项后边附加一个参数. 	      在声明标签中, 选项名后边的冒号用来提示这个选项名已经分配了一个参数.	      </P><P><BCLASS="COMMAND">getopts</B>结构通常都组成一组放在一个<AHREF="loops1.html#WHILELOOPREF">while循环</A>中, 			循环过程中每次处理一个选项和参数,			然后增加隐含变量<CODECLASS="VARNAME">$OPTIND</CODE>的值, 再进行下一次的处理. 	      </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>		<P></P><OLTYPE="1"><LI><P>通过命令行传递到脚本中的参数前边必须加上一个减号(<CODECLASS="OPTION">-</CODE>). 		      <CODECLASS="OPTION">-</CODE>是一个前缀, 		      这样<BCLASS="COMMAND">getopts</B>命令把这个参数看作为一个<EM>选项</EM>.		      事实上, <BCLASS="COMMAND">getopts</B>不会处理不带<CODECLASS="OPTION">-</CODE>前缀的参数,			  如果第一个参数就没有<CODECLASS="OPTION">-</CODE>, 			  那么将会结束选项的处理.		      </P></LI><LI><P><BCLASS="COMMAND">getopts</B>的<BCLASS="COMMAND">while</B>循环模板与标准的<BCLASS="COMMAND">while</B>循环模板有些不同, 		      没有标准循环中的中括号[]判断条件. </P></LI><LI><P><BCLASS="COMMAND">getopts</B>结构将会取代外部命令<AHREF="extmisc.html#GETOPTY">getopt</A>.		     </P></LI></OL>	      </P></TD></TR></TABLE></DIV><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;while getopts ":abcde:fg" Option  2&nbsp;# 开始的声明.  3&nbsp;# a, b, c, d, e, f, 和 g 被认为是选项(标志).  4&nbsp;# 'e' 选项后边的 : 提示这个选项需要带一个参数.  5&nbsp;# 译者注:	解释一下 'a' 前边的那个 : 的作用.  6&nbsp;#			如果选项'e'不带参数进行调用的话, 会产生一个错误信息.  7&nbsp;#			这个开头的 : 就是用来屏蔽掉这个错误信息的,   8&nbsp;#			因为我们一般都会有默认处理, 所以并不需要这个错误信息.  9&nbsp;do 10&nbsp;  case $Option in 11&nbsp;    a ) # 对选项'a'作些操作. 12&nbsp;    b ) # 对选项'b'作些操作. 13&nbsp;    ...                                            14&nbsp;    e)  # 对选项'e'作些操作, 同时处理一下$OPTARG, 15&nbsp;        # 这个变量里边将保存传递给选项"e"的参数. 16&nbsp;    ...                                            17&nbsp;    g ) # 对选项'g'作些操作. 18&nbsp;  esac 19&nbsp;done 20&nbsp;shift $(($OPTIND - 1)) 21&nbsp;# 将参数指针向下移动. 22&nbsp; 23&nbsp;# 所有这些远没有它看起来的那么复杂.&#60;嘿嘿&#62;. 24&nbsp;	      </PRE></FONT></TD></TR></TABLE></P><DIVCLASS="EXAMPLE"><HR><ANAME="EX33"></A><P><B>例子 11-20. 使用<BCLASS="COMMAND">getopts</B>命令来来读取传递给脚本的选项/参数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# 练习 getopts 和 OPTIND  3&nbsp;# 在Bill Gradwohl的建议下, 这个脚本于 10/09/03 被修改.  4&nbsp;  5&nbsp;  6&nbsp;# 在这里我们将学习如何使用 'getopts' 来处理脚本的命令行参数.  7&nbsp;# 参数被作为"选项"(标志)来解析, 并且对选项分配参数.   8&nbsp;  9&nbsp;# 试一下, 使用如下方法来调用这个脚本 10&nbsp;# 'scriptname -mn' 11&nbsp;# 'scriptname -oq qOption' (qOption 可以是任意的哪怕有些诡异字符的字符串.) 12&nbsp;# 'scriptname -qXXX -r' 13&nbsp;# 14&nbsp;# 'scriptname -qr'    - 意外的结果, "r" 将被看成是选项 "q" 的参数. 15&nbsp;# 'scriptname -q -r'  - 意外的结果, 同上. 16&nbsp;# 'scriptname -mnop -mnop'  - 意外的结果 17&nbsp;# (OPTIND在选项刚传递进来的地方是不可靠的).  18&nbsp;# (译者注: 也就是说OPTIND只是一个参数指针, 指向下一个参数的位置. 19&nbsp;#  比如:	-mnop 在mno处理的位置OPTION都为1, 而到p的处理就变成2,  20&nbsp;#			-m -n -o 在m的时候OPTION为2, 而n为3, o为4, 21&nbsp;#			也就是说它总指向下一个位置).  22&nbsp;# 23&nbsp;#  如果选项需要一个参数的话("flag:"), 那么它将获取 24&nbsp;#+ 命令行上紧挨在它后边的任何字符. 25&nbsp; 26&nbsp;NO_ARGS=0  27&nbsp;E_OPTERROR=65 28&nbsp; 29&nbsp;if [ $# -eq "$NO_ARGS" ]  # 不带命令行参数就调用脚本? 30&nbsp;then 31&nbsp;  echo "Usage: `basename $0` options (-mnopqrs)" 32&nbsp;  exit $E_OPTERROR        # 如果没有参数传递进来, 那么就退出脚本, 并且解释此脚本的用法. 33&nbsp;fi   34&nbsp;# 用法: scriptname -options 35&nbsp;# 注意: 必须使用破折号 (-)  36&nbsp; 37&nbsp; 38&nbsp;while getopts ":mnopq:rs" Option 39&nbsp;do 40&nbsp;  case $Option in 41&nbsp;    m     ) echo "Scenario #1: option -m-   [OPTIND=${OPTIND}]";; 42&nbsp;    n | o ) echo "Scenario #2: option -$Option-   [OPTIND=${OPTIND}]";; 43&nbsp;    p     ) echo "Scenario #3: option -p-   [OPTIND=${OPTIND}]";; 44&nbsp;    q     ) echo "Scenario #4: option -q-\ 45&nbsp; with argument \"$OPTARG\"   [OPTIND=${OPTIND}]";; 46&nbsp;    #  注意, 选项'q'必须分配一个参数,  47&nbsp;    #+ 否则, 默认将失败. 48&nbsp;    r | s ) echo "Scenario #5: option -$Option-";; 49&nbsp;    *     ) echo "Unimplemented option chosen.";;   # 默认情况的处理 50&nbsp;  esac 51&nbsp;done 52&nbsp; 53&nbsp;shift $(($OPTIND - 1)) 54&nbsp;#  (译者注: shift命令是可以带参数的, 参数就是移动的个数) 55&nbsp;#  将参数指针减1, 这样它将指向下一个参数. 56&nbsp;#  $1 现在引用的是命令行上的第一个非选项参数, 57&nbsp;#+ 如果有一个这样的参数存在的话. 58&nbsp; 59&nbsp;exit 0 60&nbsp; 61&nbsp;#   就像 Bill Gradwohl 所描述的, 62&nbsp;#  "getopts机制允许指定一个参数,  63&nbsp;#+ 但是scriptname -mnop -mnop就是一种比较特殊的情况,  64&nbsp;#+ 因为在使用OPTIND的时候, 没有可靠的方法来区分到底传递进来了什么东西."</PRE></FONT></TD></TR></TABLE><HR></DIV></DD></DL></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="INTSCRBEH1"></A>脚本行为</B></P><DL><DT><ANAME="SOURCEREF"></A><BCLASS="COMMAND">source</B>, <SPANCLASS="TOKEN">.</SPAN> (<AHREF="special-chars.html#DOTREF">点</A> 命令)</DT><DD><P>当在命令行中调用的时候, 这个命令将会执行一个脚本.	      当在脚本中调用的时候, 		  <KBDCLASS="USERINPUT">source file-name</KBD> 将会加载<TTCLASS="FILENAME">file-name</TT>文件. 		  sourc一个文件(或点命令)将会在脚本中<EM>引入</EM>代码, 	     并将这些代码附加到脚本中(与<EM>C</EM>语言中的<KBDCLASS="USERINPUT">#include</KBD>指令效果相同). 	     最终的结果就像是在使用<SPANCLASS="QUOTE">"source"</SPAN>的行上插入了相应文件的内容. 	     在多个脚本需要引用相同的数据, 或者需要使用函数库的情况下, 	     这个命令非常有用. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX38"></A><P><B>例子 11-21. <SPANCLASS="QUOTE">"includ"</SPAN>一个数据文件</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;  3&nbsp;. data-file    # 加载一个数据文件.  4&nbsp;# 与"source data-file"效果相同, 但是更具可移植性.  5&nbsp;  6&nbsp;#  文件"data-file"必须存在于当前工作目录,   7&nbsp;#+ 因为这个文件是使用'basename'来引用的.   8&nbsp;  9&nbsp;# 现在, 引用这个文件中的一些数据.  10&nbsp; 11&nbsp;echo "variable1 (from data-file) = $variable1" 12&nbsp;echo "variable3 (from data-file) = $variable3" 13&nbsp; 14&nbsp;let "sum = $variable2 + $variable4" 15&nbsp;echo "Sum of variable2 + variable4 (from data-file) = $sum" 16&nbsp;echo "message1 (from data-file) is \"$message1\"" 17&nbsp;# 注意:                             将双引号转义 18&nbsp; 19&nbsp;print_message This is the message-print function in the data-file. 20&nbsp; 21&nbsp; 22&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><P>上边<AHREF="internal.html#EX38">例子 11-21</A>所使用的数据文件<TTCLASS="FILENAME">data-file</TT>,  				  必须和上边的脚本放在同一目录下. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;# 这是需要被脚本加载的数据文件.  2&nbsp;# 这种文件可以包含变量, 函数, 等等.  3&nbsp;# 在脚本中可以通过'source'或者'.'命令来加载.  4&nbsp;                                               5&nbsp;# 让我们初始化一些变量.  6&nbsp;  7&nbsp;variable1=22  8&nbsp;variable2=474  9&nbsp;variable3=5 10&nbsp;variable4=97 11&nbsp; 12&nbsp;message1="Hello, how are you?" 13&nbsp;mess

⌨️ 快捷键说明

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