list-cons.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 622 行
HTML
622 行
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>列表结构</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="高级主题"HREF="part4.html"><LINKREL="PREVIOUS"TITLE="别名"HREF="aliases.html"><LINKREL="NEXT"TITLE="数组"HREF="arrays.html"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="aliases.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="arrays.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="LIST-CONS"></A>25. 列表结构</H1><P><ANAME="LISTCONSREF"></A></P><P><SPANCLASS="QUOTE">"与列表"</SPAN>和<SPANCLASS="QUOTE">"或列表"</SPAN>结构能够提供一种手段, 这种手段能够用来处理一串连续的命令. 这样就可以有效的替换掉嵌套的<BCLASS="COMMAND">if</B>/<BCLASS="COMMAND">then</B>结构, 甚至能够替换掉<BCLASS="COMMAND">case</B>语句. </P><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="LCONS1"></A>把命令连接到一起</B></P><DL><DT>与列表</DT><DD><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 command-1 && command-2 && command-3 && ... command-n</PRE></FONT></TD></TR></TABLE> 如果每个命令执行后都返回<SPANCLASS="RETURNVALUE">true</SPAN>(0)的话, 那么命令将会依次执行下去. 如果其中的某个命令返回<SPANCLASS="RETURNVALUE">false</SPAN>(非零值)的话, 那么这个命令链就会被打断, 也就是结束执行, (那么第一个返回<SPANCLASS="RETURNVALUE">false</SPAN>的命令, 就是最后一个执行的命令, 其后的命令都不会执行). </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX64"></A><P><B>例子 25-1. 使用<SPANCLASS="QUOTE">"与列表"</SPAN>来测试命令行参数</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # "与列表" 3 4 if [ ! -z "$1" ] && echo "Argument #1 = $1" && [ ! -z "$2" ] && echo "Argument #2 = $2" 5 then 6 echo "At least 2 arguments passed to script." 7 # 所有连接起来的命令都返回true. 8 else 9 echo "Less than 2 arguments passed to script." 10 # 整个命令列表中至少有一个命令返回false. 11 fi 12 # 注意, "if [ ! -z $1 ]"也可以, 但它是有所假定的等价物. 13 # if [ -n $1 ] 这个不行. 14 # 然而, 如果加了引用就行了. 15 # if [ -n "$1" ] 这样就行了. 16 # 小心! 17 # 最好将你要测试的变量引用起来, 这么做是非常好的习惯. 18 19 20 # 下面这段代码与上面代码是等价的, 不过下面这段代码使用的是"纯粹"的if/then结构. 21 if [ ! -z "$1" ] 22 then 23 echo "Argument #1 = $1" 24 fi 25 if [ ! -z "$2" ] 26 then 27 echo "Argument #2 = $2" 28 echo "At least 2 arguments passed to script." 29 else 30 echo "Less than 2 arguments passed to script." 31 fi 32 # 这么写的话, 行数太多了, 没有"与列表"来的精简. 33 34 35 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ANDLIST2"></A><P><B>例子 25-2. 使用<SPANCLASS="QUOTE">"与列表"</SPAN>来测试命令行参数的另一个例子</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 ARGS=1 # 期望的参数个数. 4 E_BADARGS=65 # 如果传递的参数个数不正确, 那么给出这个退出码. 5 6 test $# -ne $ARGS && echo "Usage: `basename $0` $ARGS argument(s)" && exit $E_BADARGS 7 # 如果"条件1"测试为true (表示传递给脚本的参数个数不对), 8 #+ 则余下的命令会被执行, 并且脚本将结束运行. 9 10 # 只有当上面的测试条件为false的时候, 这行代码才会被执行. 11 echo "Correct number of arguments passed to this script." 12 13 exit 0 14 15 # 为了检查退出码, 在脚本结束的时候可以使用"echo $?"来查看退出码. </PRE></FONT></TD></TR></TABLE><HR></DIV><P><ANAME="ANDDEFAULT"></A></P><P> 当然, <EM>与列表</EM>也可以给变量<EM>设置</EM>默认值. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 arg1=$@ # 不管怎样, 将$arg1设置为命令行参数. 2 3 [ -z "$arg1" ] && arg1=DEFAULT 4 # 如果没有指定命令行参数, 则把$arg1设置为DEFAULT. </PRE></FONT></TD></TR></TABLE> </P></DD><DT>或列表</DT><DD><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 command-1 || command-2 || command-3 || ... command-n</PRE></FONT></TD></TR></TABLE> 如果每个命令都返回<SPANCLASS="RETURNVALUE">false</SPAN>, 那么命令链就会执行下去. 一旦有一个命令返回<SPANCLASS="RETURNVALUE">true</SPAN>, 命令链就会被打断, 也就是结束执行, (第一个返回<SPANCLASS="RETURNVALUE">true</SPAN>的命令将会是最后一个执行的命令). 显然, 这和<SPANCLASS="QUOTE">"与列表"</SPAN>完全相反. </P><DIVCLASS="EXAMPLE"><HR><ANAME="EX65"></A><P><B>例子 25-3. 将<SPANCLASS="QUOTE">"或列表"</SPAN>和<SPANCLASS="QUOTE">"与列表"</SPAN>结合使用</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 # delete.sh, 不是很聪明的文件删除方法. 4 # Usage: delete filename 5 6 E_BADARGS=65 7 8 if [ -z "$1" ] 9 then 10 echo "Usage: `basename $0` filename" 11 exit $E_BADARGS # 没有参数? 退出脚本. 12 else 13 file=$1 # 设置文件名. 14 fi 15 16 17 [ ! -f "$file" ] && echo "File \"$file\" not found. \ 18 Cowardly refusing to delete a nonexistent file." 19 # 与列表, 在文件不存在时将会给出错误信息. 20 # 注意echo命令使用了一个续行符, 这样下一行的内容, 也会作为echo命令的参数. 21 22 [ ! -f "$file" ] || (rm -f $file; echo "File \"$file\" deleted.") 23 # 或列表, 如果文件存在, 那就删除此文件. 24 25 # 注意, 上边的两个逻辑相反. 26 # 与列表在true的情况下才执行, 或列表在false的时候才执行. 27 28 exit 0</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>如果<SPANCLASS="QUOTE">"或列表"</SPAN>中的第一个命令返回<SPANCLASS="RETURNVALUE">true</SPAN>, 那么, <SPANCLASS="QUOTE">"或列表"</SPAN>中的第一个命令还是<TTCLASS="REPLACEABLE"><I>会</I></TT>执行. </P></TD></TR></TABLE></DIV></DD></DL></DIV><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 # ==> 下面的片断摘自于脚本/etc/rc.d/init.d/single, 这个脚本由Miquel van Smoorenburg所编写. 2 #+==> 用于展示"与"/"或"列表的使用. 3 # ==> "箭头"注释是由本书作者添加的. 4 5 [ -x /usr/bin/clear ] && /usr/bin/clear 6 # ==> 如果/usr/bin/clear存在, 那么就调用它. 7 # ==> 在调用一个命令前, 检查一下它是否存在. 8 #+==> 这样可以避免错误信息, 和其他愚蠢的结果. 9 10 # ==> . . . 11 12 # 如果他们想在单用户模式下运行某些程序, 可能也会运行它... 13 for i in /etc/rc1.d/S[0-9][0-9]* ; do 14 # 检查一下脚本是否在那里. 15 [ -x "$i" ] || continue 16 # ==> 如果在$PWD中没发现相应的文件, 17 #+==> 则会使用"continue"跳过本次循环. 18 19 # 不接受备份文件, 也不接受由rpm产生的文件. 20 case "$1" in 21 *.rpmsave|*.rpmorig|*.rpmnew|*~|*.orig) 22 continue;; 23 esac 24 [ "$i" = "/etc/rc1.d/S00single" ] && continue 25 # ==> 设置脚本名, 但现在还不执行它. 26 $i start 27 done 28 29 # ==> . . .</PRE></FONT></TD></TR></TABLE></P><DIVCLASS="IMPORTANT"><P></P><TABLECLASS="IMPORTANT"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/important.gif"HSPACE="5"ALT="Important"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><KBDCLASS="USERINPUT">与列表</KBD>和<KBDCLASS="USERINPUT">或列表</KBD>的<AHREF="exit-status.html#EXITSTATUSREF">退出状态码</A>由最后一个命令的退出状态所决定. </P></TD></TR></TABLE></DIV><P>可以灵活的将<SPANCLASS="QUOTE">"与"</SPAN>/<SPANCLASS="QUOTE">"或"</SPAN>列表组合在一起, 但是这么做的话, 会使得逻辑变得很复杂, 并且需要经过仔细的测试. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 false && true || echo false # false 2 3 # 与下面的结果相同 4 ( false && true ) || echo false # false 5 # But *not* 6 false && ( true || echo false ) # (没有输出) 7 8 # 注意, 以从做到右的顺序进行分组与求值, 9 #+ 这是因为逻辑操作符"&&"和"||"具有相同的优先级. 10 11 # 最好避免这么复杂的情况, 除非你非常了解你到底在做什么. 12 13 # 感谢, S.C.</PRE></FONT></TD></TR></TABLE> </P><P>也请参考<AHREF="contributed-scripts.html#DAYSBETWEEN">例子 A-7</A>和<AHREF="fto.html#BROKENLINK">例子 7-4</A>, 这两个例子展示了如何使用<KBDCLASS="USERINPUT">与/或列表</KBD>来测试变量. </P></DIV><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="aliases.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="arrays.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">别名</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part4.html"ACCESSKEY="U">上一级</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">数组</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?