📄 assortedtips.html
字号:
><TD><PRECLASS="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 # An integer is either equal to 0 or not equal to 0. 8 # 2>/dev/null suppresses error message. 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" # Would give error if $1 not integer. 17 echo "Sum = $sum" 18 19 # Any variable, not just a command line parameter, can be tested this way. 20 21 exit 0</PRE></TD></TR></TABLE> </P></LI><LI><P><ANAME="RVT"></A>The 0 - 255 range for function return values is a severe limitation. Global variables and other workarounds are often problematic. An alternative method for a function to communicate a value back to the main body of the script is to have the function write to <TTCLASS="FILENAME">stdout</TT> (usually with <AHREF="internal.html#ECHOREF">echo</A>) the <SPANCLASS="QUOTE">"return value,"</SPAN> and assign this to a variable. This is actually a variant of <AHREF="commandsub.html#COMMANDSUBREF">command substitution.</A></P><DIVCLASS="EXAMPLE"><HR><ANAME="MULTIPLICATION"></A><P><B>Example 33-15. Return value trickery</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # multiplication.sh 3 4 multiply () # Multiplies params passed. 5 { # Will accept a variable number of args. 6 7 local product=1 8 9 until [ -z "$1" ] # Until uses up arguments passed... 10 do 11 let "product *= $1" 12 shift 13 done 14 15 echo $product # Will not echo to stdout, 16 } #+ since this will be assigned to a variable. 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></TD></TR></TABLE><HR></DIV><P>The same technique also works for alphanumeric strings. This means that a function can <SPANCLASS="QUOTE">"return"</SPAN> a non-numeric value.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 capitalize_ichar () # Capitalizes initial character 2 { #+ of argument string(s) passed. 3 4 string0="$@" # Accepts multiple arguments. 5 6 firstchar=${string0:0:1} # First character. 7 string1=${string0:1} # Rest of string(s). 8 9 FirstChar=`echo "$firstchar" | tr a-z A-Z` 10 # Capitalize first character. 11 12 echo "$FirstChar$string1" # Output to 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></TD></TR></TABLE> </P><P>It is even possible for a function to <SPANCLASS="QUOTE">"return"</SPAN> multiple values with this method.</P><DIVCLASS="EXAMPLE"><HR><ANAME="SUMPRODUCT"></A><P><B>Example 33-16. Even more return value trickery</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # sum-product.sh 3 # A function may "return" more than one value. 4 5 sum_and_product () # Calculates both sum and product of passed args. 6 { 7 echo $(( $1 + $2 )) $(( $1 * $2 )) 8 # Echoes to stdout each calculated value, separated by space. 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` # Assigns output of function. 21 sum=`echo "$retval" | awk '{print $1}'` # Assigns first field. 22 product=`echo "$retval" | awk '{print $2}'` # Assigns second field. 23 24 echo "$first + $second = $sum" 25 echo "$first * $second = $product" 26 echo 27 28 exit 0</PRE></TD></TR></TABLE><HR></DIV></LI><LI><P><ANAME="PASSARRAY"></A></P><P>Next in our bag of tricks are techniques for passing an <AHREF="arrays.html#ARRAYREF">array</A> to a <AHREF="functions.html#FUNCTIONREF">function</A>, then <SPANCLASS="QUOTE">"returning"</SPAN> an array back to the main body of the script.</P><P>Passing an array involves loading the space-separated elements of the array into a variable with <AHREF="commandsub.html#COMMANDSUBREF">command substitution</A>. <ANAME="RETARRAY"></A>Getting an array back as the <SPANCLASS="QUOTE">"return value"</SPAN> from a function uses the previously mentioned strategem of <AHREF="internal.html#ECHOREF">echoing</A> the array in the function, then invoking command substitution and the <BCLASS="COMMAND">( ... )</B> operator to assign it to an array.</P><DIVCLASS="EXAMPLE"><HR><ANAME="ARRFUNC"></A><P><B>Example 33-17. Passing and returning arrays</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # array-function.sh: Passing an array to a function and... 3 # "returning" an array from a function 4 5 6 Pass_Array () 7 { 8 local passed_array # Local variable. 9 passed_array=( `echo "$1"` ) 10 echo "${passed_array[@]}" 11 # List all the elements of the new array 12 #+ declared and set within the function. 13 } 14 15 16 original_array=( element1 element2 element3 element4 element5 ) 17 18 echo 19 echo "original_array = ${original_array[@]}" 20 # List all elements of original array. 21 22 23 # This is the trick that permits passing an array to a function. 24 # ********************************** 25 argument=`echo ${original_array[@]}` 26 # ********************************** 27 # Pack a variable 28 #+ with all the space-separated elements of the original array. 29 # 30 # Note that attempting to just pass the array itself will not work. 31 32 33 # This is the trick that allows grabbing an array as a "return value". 34 # ***************************************** 35 returned_array=( `Pass_Array "$argument"` ) 36 # ***************************************** 37 # Assign 'echoed' output of function to array variable. 38 39 echo "returned_array = ${returned_array[@]}" 40 41 echo "=============================================================" 42 43 # Now, try it again, 44 #+ attempting to access (list) the array from outside the function. 45 Pass_Array "$argument" 46 47 # The function itself lists the array, but... 48 #+ accessing the array from outside the function is forbidden. 49 echo "Passed array (within function) = ${passed_array[@]}" 50 # NULL VALUE since this is a variable local to the function. 51 52 echo 53 54 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>For a more elaborate example of passing arrays to functions, see <AHREF="contributed-scripts.html#LIFESLOW">Example A-10</A>.</P></LI><LI><P><ANAME="CSTYLE"></A></P><P>Using the <AHREF="dblparens.html">double parentheses construct</A>, it is possible to use C-style syntax for setting and incrementing/decrementing variables and in <AHREF="loops.html#FORLOOPREF1">for</A> and <AHREF="loops.html#WHILELOOPREF">while</A> loops. See <AHREF="loops.html#FORLOOPC">Example 10-12</A> and <AHREF="loops.html#WHLOOPC">Example 10-17</A>.</P></LI><LI><P><ANAME="SETPUM"></A></P><P>Setting the <AHREF="variables2.html#PATHREF">path</A> and <AHREF="system.html#UMASKREF">umask</A> at the beginning of a script makes it more <SPANCLASS="QUOTE">"portable"</SPAN> -- more likely to run on a <SPANCLASS="QUOTE">"foreign"</SPAN> machine whose user may have bollixed up the <TTCLASS="VARNAME">$PATH</TT> and <BCLASS="COMMAND">umask</B>. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 PATH=/bin:/usr/bin:/usr/local/bin ; export PATH 3 umask 022 # Files that the script creates will have 755 permission. 4 5 # Thanks to Ian D. Allen, for this tip.</PRE></TD></TR></TABLE></P></LI><LI><P><ANAME="FILTEROUTP"></A></P><P>A useful scripting technique is to <SPANCLASS="emphasis"><ICLASS="EMPHASIS">repeatedly</I></SPAN> feed the output of a filter (by piping) back to the <SPANCLASS="emphasis"><ICLASS="EMPHASIS">same filter</I></SPAN>, but with a different set of arguments and/or options. Especially suitable for this are <AHREF="textproc.html#TRREF">tr</A> and <AHREF="textproc.html#GREPREF">grep</A>.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 # From "wstrings.sh" example. 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></TD></TR></TABLE> </P><DIVCLASS="EXAMPLE"><HR><ANAME="AGRAM"></A><P><B>Example 33-18. Fun with anagrams</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # agram.sh: Playing games with anagrams. 3 4 # Find anagrams of... 5 LETTERSET=etaoinshrdlu 6 FILTER='.......' # How many letters minimum? 7 # 1234567 8 9 anagram "$LETTERSET" | # Find all anagrams of the letterset... 10 grep "$FILTER" | # With at least 7 letters, 11 grep '^is' | # starting with 'is' 12 grep -v 's$' | # no plurals 13 grep -v 'ed$' # no past tense verbs 14 # Possible to add many combinations of conditions and filters. 15 16 # Uses "anagram" utility 17 #+ that is part of the author's "yawl" word list package. 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 # End of code. 22 23 24 bash$ sh agram.sh 25 islander 26 isolate 27 isolead 28 isotheral 29 30 31 32 # Exercises: 33 # --------- 34 # Modify this script to take the LETTERSET as a command-line parameter. 35 # Parameterize the filters in lines 11 - 13 (as with $FILTER), 36 #+ so that they can be specified by passing arguments to a function. 37 38 # For a slightly different approach to anagramming, 39 #+ see the agram2.sh script.</PRE></TD></TR></TABLE><HR></DIV><P>See also <AHREF="procref1.html#CONSTAT">Example 27-3</A>, <AHREF="textproc.html#CRYPTOQUOTE">Example 15-24</A>, and <AHREF="contributed-scripts.html#SOUNDEX">Example A-9</A>.</P></LI><LI><P><ANAME="COMMBLAHD"></A></P><P>Use <SPANCLASS="QUOTE">"<AHREF="here-docs.html#ANONHEREDOC0">anonymous here documents</A>"</SPAN> to comment out blocks of code, to save having to individually comment out each line with a <SPANCLASS="TOKEN">#</SPAN>. See <AHREF="here-docs.html#COMMENTBLOCK">Example 18-11</A>.</P></LI><LI><P><ANAME="WHATISREF3"></A></P><P>Running a script on a machine that relies on a command that might not be installed is dangerous. Use <AHREF="filearchiv.html#WHATISREF">whatis</A> to avoid potential problems with this.</P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 CMD=command1 # First choice. 2 PlanB=command2 # Fallback option. 3 4 command_test=$(whatis "$CMD" | grep 'nothing appropriate') 5 # If 'command1' not found on system , 'whatis' will return 6 #+ "command1: nothing appropriate." 7 # 8 # A safer alternative is:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -