internal.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 3,324 行 · 第 1/5 页
HTML
3,324 行
><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # unset.sh: Unset 一个变量. 3 4 variable=hello # 初始化. 5 echo "variable = $variable" 6 7 unset variable # Unset. 8 # 与 variable= 效果相同. 9 echo "(unset) variable = $variable" # $variable 设为 null. 10 11 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 #!/bin/bash 2 3 # 这是"求列的和"脚本的另外一个版本(col-totaler.sh) 4 #+ 那个脚本可以把目标文件中的指定的列上的所有数字全部累加起来,求和. 5 # 这个版本将把一个变量通过export的形式传递到'awk'中 . . . 6 #+ 并且把awk脚本放到一个变量中. 7 8 9 ARGS=2 10 E_WRONGARGS=65 11 12 if [ $# -ne "$ARGS" ] # 检查命令行参数的个数. 13 then 14 echo "Usage: `basename $0` filename column-number" 15 exit $E_WRONGARGS 16 fi 17 18 filename=$1 19 column_number=$2 20 21 #===== 上边的这部分,与原始脚本完全一样 =====# 22 23 export column_number 24 # 将列号export出来, 这样后边的进程就可用了. 25 26 27 # ----------------------------------------------- 28 awkscript='{ total += $ENVIRON["column_number"] } 29 END { print total }' 30 # 是的, 变量可以保存awk脚本. 31 # ----------------------------------------------- 32 33 # 现在, 运行这个awk脚本. 34 awk "$awkscript" "$filename" 35 36 # 感谢, Stephane Chazelas. 37 38 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 while getopts ":abcde:fg" Option 2 # 开始的声明. 3 # a, b, c, d, e, f, 和 g 被认为是选项(标志). 4 # 'e' 选项后边的 : 提示这个选项需要带一个参数. 5 # 译者注: 解释一下 'a' 前边的那个 : 的作用. 6 # 如果选项'e'不带参数进行调用的话, 会产生一个错误信息. 7 # 这个开头的 : 就是用来屏蔽掉这个错误信息的, 8 # 因为我们一般都会有默认处理, 所以并不需要这个错误信息. 9 do 10 case $Option in 11 a ) # 对选项'a'作些操作. 12 b ) # 对选项'b'作些操作. 13 ... 14 e) # 对选项'e'作些操作, 同时处理一下$OPTARG, 15 # 这个变量里边将保存传递给选项"e"的参数. 16 ... 17 g ) # 对选项'g'作些操作. 18 esac 19 done 20 shift $(($OPTIND - 1)) 21 # 将参数指针向下移动. 22 23 # 所有这些远没有它看起来的那么复杂.<嘿嘿>. 24 </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 #!/bin/bash 2 # 练习 getopts 和 OPTIND 3 # 在Bill Gradwohl的建议下, 这个脚本于 10/09/03 被修改. 4 5 6 # 在这里我们将学习如何使用 'getopts' 来处理脚本的命令行参数. 7 # 参数被作为"选项"(标志)来解析, 并且对选项分配参数. 8 9 # 试一下, 使用如下方法来调用这个脚本 10 # 'scriptname -mn' 11 # 'scriptname -oq qOption' (qOption 可以是任意的哪怕有些诡异字符的字符串.) 12 # 'scriptname -qXXX -r' 13 # 14 # 'scriptname -qr' - 意外的结果, "r" 将被看成是选项 "q" 的参数. 15 # 'scriptname -q -r' - 意外的结果, 同上. 16 # 'scriptname -mnop -mnop' - 意外的结果 17 # (OPTIND在选项刚传递进来的地方是不可靠的). 18 # (译者注: 也就是说OPTIND只是一个参数指针, 指向下一个参数的位置. 19 # 比如: -mnop 在mno处理的位置OPTION都为1, 而到p的处理就变成2, 20 # -m -n -o 在m的时候OPTION为2, 而n为3, o为4, 21 # 也就是说它总指向下一个位置). 22 # 23 # 如果选项需要一个参数的话("flag:"), 那么它将获取 24 #+ 命令行上紧挨在它后边的任何字符. 25 26 NO_ARGS=0 27 E_OPTERROR=65 28 29 if [ $# -eq "$NO_ARGS" ] # 不带命令行参数就调用脚本? 30 then 31 echo "Usage: `basename $0` options (-mnopqrs)" 32 exit $E_OPTERROR # 如果没有参数传递进来, 那么就退出脚本, 并且解释此脚本的用法. 33 fi 34 # 用法: scriptname -options 35 # 注意: 必须使用破折号 (-) 36 37 38 while getopts ":mnopq:rs" Option 39 do 40 case $Option in 41 m ) echo "Scenario #1: option -m- [OPTIND=${OPTIND}]";; 42 n | o ) echo "Scenario #2: option -$Option- [OPTIND=${OPTIND}]";; 43 p ) echo "Scenario #3: option -p- [OPTIND=${OPTIND}]";; 44 q ) echo "Scenario #4: option -q-\ 45 with argument \"$OPTARG\" [OPTIND=${OPTIND}]";; 46 # 注意, 选项'q'必须分配一个参数, 47 #+ 否则, 默认将失败. 48 r | s ) echo "Scenario #5: option -$Option-";; 49 * ) echo "Unimplemented option chosen.";; # 默认情况的处理 50 esac 51 done 52 53 shift $(($OPTIND - 1)) 54 # (译者注: shift命令是可以带参数的, 参数就是移动的个数) 55 # 将参数指针减1, 这样它将指向下一个参数. 56 # $1 现在引用的是命令行上的第一个非选项参数, 57 #+ 如果有一个这样的参数存在的话. 58 59 exit 0 60 61 # 就像 Bill Gradwohl 所描述的, 62 # "getopts机制允许指定一个参数, 63 #+ 但是scriptname -mnop -mnop就是一种比较特殊的情况, 64 #+ 因为在使用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 #!/bin/bash 2 3 . data-file # 加载一个数据文件. 4 # 与"source data-file"效果相同, 但是更具可移植性. 5 6 # 文件"data-file"必须存在于当前工作目录, 7 #+ 因为这个文件是使用'basename'来引用的. 8 9 # 现在, 引用这个文件中的一些数据. 10 11 echo "variable1 (from data-file) = $variable1" 12 echo "variable3 (from data-file) = $variable3" 13 14 let "sum = $variable2 + $variable4" 15 echo "Sum of variable2 + variable4 (from data-file) = $sum" 16 echo "message1 (from data-file) is \"$message1\"" 17 # 注意: 将双引号转义 18 19 print_message This is the message-print function in the data-file. 20 21 22 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 # 这是需要被脚本加载的数据文件. 2 # 这种文件可以包含变量, 函数, 等等. 3 # 在脚本中可以通过'source'或者'.'命令来加载. 4 5 # 让我们初始化一些变量. 6 7 variable1=22 8 variable2=474 9 variable3=5 10 variable4=97 11 12 message1="Hello, how are you?" 13 mess
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?