📄 assortedtips.html
字号:
CLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 SUCCESS=0 4 E_BADINPUT=65 5 6 test "$1" -ne 0 -o "$1" -eq 0 2>/dev/null 7 # 整数要不就是0, 要不就是非0值. (译者注: 感觉像废话 . . .) 8 # 2>/dev/null禁止输出错误信息. 9 10 if [ $? -ne "$SUCCESS" ] 11 then 12 echo "Usage: `basename $0` integer-input" 13 exit $E_BADINPUT 14 fi 15 16 let "sum = $1 + 25" # 如果$1不是整数, 就会产生错误. 17 echo "Sum = $sum" 18 19 # 任何变量都可以使用这种方法来测试, 而不仅仅适用于命令行参数. 20 21 exit 0</PRE></FONT></TD></TR></TABLE> </P></LI><LI><P><ANAME="RVT"></A>函数的返回值严格限制在0 - 255之间. 使用全局变量或者其他方法来代替函数返回值, 通常都很容易产生问题. 从函数中, 返回一个值到脚本主体的另一个办法是, 将这个"返回值"写入到<TTCLASS="FILENAME">stdout</TT>(通常都使用<AHREF="internal.html#ECHOREF">echo</A>命令), 然后将其赋值给一个变量. 这种做法其实就是<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>的一个变种. </P><DIVCLASS="EXAMPLE"><HR><ANAME="MULTIPLICATION"></A><P><B>例子 33-15. 返回值小技巧</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # multiplication.sh 3 4 multiply () # 将乘数作为参数传递进来. 5 { # 可以接受多个参数. 6 7 local product=1 8 9 until [ -z "$1" ] # 直到处理完所有的参数... 10 do 11 let "product *= $1" 12 shift 13 done 14 15 echo $product # 不会echo到stdout, 16 } #+ 因为要把它赋值给一个变量. 17 18 mult1=15383; mult2=25211 19 val1=`multiply $mult1 $mult2` 20 echo "$mult1 X $mult2 = $val1" 21 # 387820813 22 23 mult1=25; mult2=5; mult3=20 24 val2=`multiply $mult1 $mult2 $mult3` 25 echo "$mult1 X $mult2 X $mult3 = $val2" 26 # 2500 27 28 mult1=188; mult2=37; mult3=25; mult4=47 29 val3=`multiply $mult1 $mult2 $mult3 $mult4` 30 echo "$mult1 X $mult2 X $mult3 X $mult4 = $val3" 31 # 8173300 32 33 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>相同的技术也可以用在字符串上. 这意味着函数可以<SPANCLASS="QUOTE">"返回"</SPAN>非数字的值. </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 capitalize_ichar () # 将传递进来的字符串的 2 { #+ 首字母转换为大写. 3 4 string0="$@" # 能够接受多个参数. 5 6 firstchar=${string0:0:1} # 首字母. 7 string1=${string0:1} # 余下的字符. 8 9 FirstChar=`echo "$firstchar" | tr a-z A-Z` 10 # 将首字母转换为大写. 11 12 echo "$FirstChar$string1" # 输出到stdout. 13 14 } 15 16 newstring=`capitalize_ichar "every sentence should start with a capital letter."` 17 echo "$newstring" # Every sentence should start with a capital letter.</PRE></FONT></TD></TR></TABLE> </P><P>使用这种办法甚至能够<SPANCLASS="QUOTE">"返回"</SPAN>多个值. </P><DIVCLASS="EXAMPLE"><HR><ANAME="SUMPRODUCT"></A><P><B>例子 33-16. 返回多个值的技巧</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # sum-product.sh 3 # 可以"返回"超过一个值的函数. 4 5 sum_and_product () # 计算所有传递进来的参数的总和, 与总乘积. 6 { 7 echo $(( $1 + $2 )) $(( $1 * $2 )) 8 # 将每个计算出来的结果输出到stdout, 并以空格分隔. 9 } 10 11 echo 12 echo "Enter first number " 13 read first 14 15 echo 16 echo "Enter second number " 17 read second 18 echo 19 20 retval=`sum_and_product $first $second` # 将函数的输出赋值给变量. 21 sum=`echo "$retval" | awk '{print $1}'` # 赋值第一个域. 22 product=`echo "$retval" | awk '{print $2}'` # 赋值第二个域. 23 24 echo "$first + $second = $sum" 25 echo "$first * $second = $product" 26 echo 27 28 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV></LI><LI><P>下一个技巧, 是将<AHREF="arrays.html#ARRAYREF">数组</A>传递给<AHREF="functions.html#FUNCTIONREF">函数</A>的技术, 然后<SPANCLASS="QUOTE">"返回"</SPAN>一个数组给脚本的主体. </P><P>使用<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>将数组中的所有元素(元素之间用空格分隔)赋值给一个变量, 这样就可以将数组传递到函数中了. 我们之前提到过一种返回值的策略, 就是将要从函数中返回的内容, 用<EM>echo</EM>命令输出出来, 然后使用命令替换或者<BCLASS="COMMAND">( ... )</B>操作符, 将函数的输出(也就是我们想要得返回值)保存到一个变量中. 如果我们想让函数<SPANCLASS="QUOTE">"返回"</SPAN>数组, 当然也可以使用这种策略. </P><DIVCLASS="EXAMPLE"><HR><ANAME="ARRFUNC"></A><P><B>例子 33-17. 传递数组到函数, 从函数中返回数组</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # array-function.sh: 将数组传递到函数中与... 3 # 从函数中"返回"一个数组 4 5 6 Pass_Array () 7 { 8 local passed_array # 局部变量. 9 passed_array=( `echo "$1"` ) 10 echo "${passed_array[@]}" 11 # 列出这个新数组中的所有元素, 12 #+ 这个新数组是在函数内声明的, 也是在函数内赋值的. 13 } 14 15 16 original_array=( element1 element2 element3 element4 element5 ) 17 18 echo 19 echo "original_array = ${original_array[@]}" 20 # 列出原始数组的所有元素. 21 22 23 # 下面是关于如何将数组传递给函数的技巧. 24 # ********************************** 25 argument=`echo ${original_array[@]}` 26 # ********************************** 27 # 将原始数组中所有的元素都用空格进行分隔, 28 #+ 然后合并成一个字符串, 最后赋值给一个变量. 29 # 30 # 注意, 如果只把数组传递给函数, 那是不行的. 31 32 33 # 下面是让数组作为"返回值"的技巧. 34 # ***************************************** 35 returned_array=( `Pass_Array "$argument"` ) 36 # ***************************************** 37 # 将函数中'echo'出来的输出赋值给数组变量. 38 39 echo "returned_array = ${returned_array[@]}" 40 41 echo "=============================================================" 42 43 # 现在, 再试一次, 44 #+ 尝试一下, 在函数外面访问(列出)数组. 45 Pass_Array "$argument" 46 47 # 函数自身可以列出数组, 但是... 48 #+ 从函数外部访问数组是被禁止的. 49 echo "Passed array (within function) = ${passed_array[@]}" 50 # NULL值, 因为这个变量是函数内部的局部变量. 51 52 echo 53 54 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>如果想更加了解如何将数组传递到函数中, 请参考<AHREF="contributed-scripts.html#LIFESLOW">例子 A-10</A>, 这是一个精心制作的例子. </P></LI><LI><P>利用双括号结构, 就可以让我们使用C风格的语法, 在<AHREF="loops1.html#FORLOOPREF1">for</A>循环和<AHREF="loops1.html#WHILELOOPREF">while</A>循环中, 设置或者增加变量. 请参考<AHREF="loops1.html#FORLOOPC">例子 10-12</A>和<AHREF="loops1.html#WHLOOPC">例子 10-17</A>. </P></LI><LI><P>如果在脚本的开头设置<AHREF="internalvariables.html#PATHREF">path</A>和<AHREF="system.html#UMASKREF">umask</A>的话, 就可以增加脚本的<SPANCLASS="QUOTE">"可移植性"</SPAN> -- 即使在那些被用户将<CODECLASS="VARNAME">$PATH</CODE>和<BCLASS="COMMAND">umask</B>弄糟了的机器上, 也可以运行. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 PATH=/bin:/usr/bin:/usr/local/bin ; export PATH 3 umask 022 # 脚本创建的文件所具有的权限是755. 4 5 # 感谢Ian D. Allen提出这个技巧. </PRE></FONT></TD></TR></TABLE></P></LI><LI><P>一项很有用的技术是, <EM>重复地</EM>将一个过滤器的输出(通过管道)传递给这个相同的过滤器, 但是这两次使用不同的参数和选项. 尤其是<AHREF="textproc.html#TRREF">tr</A>和<AHREF="textproc.html#GREPREF">grep</A>, 非常适合于这种情况. </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 # 摘自例子"wstrings.sh". 2 3 wlist=`strings "$1" | tr A-Z a-z | tr '[:space:]' Z | \ 4 tr -cs '[:alpha:]' Z | tr -s '\173-\377' Z | tr Z ' '`</PRE></FONT></TD></TR></TABLE> </P><DIVCLASS="EXAMPLE"><HR><ANAME="AGRAM"></A><P><B>例子 33-18. anagram游戏</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # agram.sh: 使用anagram来玩游戏. 3 4 # 寻找anagram... 5 LETTERSET=etaoinshrdlu 6 FILTER='.......' # 最少有多少个字母? 7 # 1234567 8 9 anagram "$LETTERSET" | # 找出这个字符串中所有的anagram... 10 grep "$FILTER" | # 至少需要7个字符, 11 grep '^is' | # 以'is'开头 12 grep -v 's$' | # 不是复数(指英文单词的复数) 13 grep -v 'ed$' # 不是过去时(也指英文单词) 14 # 可以添加许多种组合条件和过滤器. 15 16 # 使用"anagram"工具, 17 #+ 这是作者的"yawl"文字表软件包中的一部分. 18 # http://ibiblio.org/pub/Linux/libs/yawl-0.3.2.tar.gz 19 # http://personal.riverusers.com/~thegrendel/yawl-0.3.2.tar.gz 20 21 exit 0 # 代码结束. 22 23 24 bash$ sh agram.sh 25 islander 26 isolate 27 isolead 28 isotheral 29 30 31 32 # 练习:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -