📄 functions.html
字号:
27 28 echo 29 30 echo "Nothing passed." 31 func2 # Called with no params 32 echo 33 34 35 echo "Zero-length parameter passed." 36 func2 "" # Called with zero-length param 37 echo 38 39 echo "Null parameter passed." 40 func2 "$uninitialized_param" # Called with uninitialized param 41 echo 42 43 echo "One parameter passed." 44 func2 first # Called with one param 45 echo 46 47 echo "Two parameters passed." 48 func2 first second # Called with two params 49 echo 50 51 echo "\"\" \"second\" passed." 52 func2 "" second # Called with zero-length first parameter 53 echo # and ASCII string as a second one. 54 55 exit 0</PRE></TD></TR></TABLE><HR></DIV><P><ANAME="FSHIFTREF"></A></P><DIVCLASS="IMPORTANT"><TABLECLASS="IMPORTANT"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/important.png"HSPACE="5"ALT="Important"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>The <AHREF="othertypesv.html#SHIFTREF">shift</A> command works on arguments passed to functions (see <AHREF="assortedtips.html#MULTIPLICATION">Example 33-15</A>).</P></TD></TR></TABLE></DIV><P>But, what about command-line arguments passed to the script? Does a function see them? Well, let's clear up the confusion.</P><DIVCLASS="EXAMPLE"><HR><ANAME="FUNCCMDLINEARG"></A><P><B>Example 23-3. Functions and command-line args passed to the script</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # func-cmdlinearg.sh 3 # Call this script with a command-line argument, 4 #+ something like $0 arg1. 5 6 7 func () 8 9 { 10 echo "$1" 11 } 12 13 echo "First call to function: no arg passed." 14 echo "See if command-line arg is seen." 15 func 16 # No! Command-line arg not seen. 17 18 echo "============================================================" 19 echo 20 echo "Second call to function: command-line arg passed explicitly." 21 func $1 22 # Now it's seen! 23 24 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>In contrast to certain other programming languages, shell scripts normally pass only value parameters to functions. Variable names (which are actually <ICLASS="FIRSTTERM">pointers</I>), if passed as parameters to functions, will be treated as string literals. <SPANCLASS="emphasis"><ICLASS="EMPHASIS">Functions interpret their arguments literally.</I></SPAN></P><P><ANAME="FUNCPOINTERS"></A></P><P><AHREF="ivr.html#IVRREF">Indirect variable references</A> (see <AHREF="bash2.html#EX78">Example 34-2</A>) provide a clumsy sort of mechanism for passing variable pointers to functions.</P><DIVCLASS="EXAMPLE"><HR><ANAME="INDFUNC"></A><P><B>Example 23-4. Passing an indirect reference to a function</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # ind-func.sh: Passing an indirect reference to a function. 3 4 echo_var () 5 { 6 echo "$1" 7 } 8 9 message=Hello 10 Hello=Goodbye 11 12 echo_var "$message" # Hello 13 # Now, let's pass an indirect reference to the function. 14 echo_var "${!message}" # Goodbye 15 16 echo "-------------" 17 18 # What happens if we change the contents of "hello" variable? 19 Hello="Hello, again!" 20 echo_var "$message" # Hello 21 echo_var "${!message}" # Hello, again! 22 23 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>The next logical question is whether parameters can be dereferenced <SPANCLASS="emphasis"><ICLASS="EMPHASIS">after</I></SPAN> being passed to a function.</P><DIVCLASS="EXAMPLE"><HR><ANAME="DEREFERENCECL"></A><P><B>Example 23-5. Dereferencing a parameter passed to a function</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # dereference.sh 3 # Dereferencing parameter passed to a function. 4 # Script by Bruce W. Clare. 5 6 dereference () 7 { 8 y=\$"$1" # Name of variable. 9 echo $y # $Junk 10 11 x=`eval "expr \"$y\" "` 12 echo $1=$x 13 eval "$1=\"Some Different Text \"" # Assign new value. 14 } 15 16 Junk="Some Text" 17 echo $Junk "before" # Some Text before 18 19 dereference Junk 20 echo $Junk "after" # Some Different Text after 21 22 exit 0</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="REFPARAMS"></A><P><B>Example 23-6. Again, dereferencing a parameter passed to a function</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # ref-params.sh: Dereferencing a parameter passed to a function. 3 # (Complex Example) 4 5 ITERATIONS=3 # How many times to get input. 6 icount=1 7 8 my_read () { 9 # Called with my_read varname, 10 #+ outputs the previous value between brackets as the default value, 11 #+ then asks for a new value. 12 13 local local_var 14 15 echo -n "Enter a value " 16 eval 'echo -n "[$'$1'] "' # Previous value. 17 # eval echo -n "[\$$1] " # Easier to understand, 18 #+ but loses trailing space in user prompt. 19 read local_var 20 [ -n "$local_var" ] && eval $1=\$local_var 21 22 # "And-list": if "local_var" then set "$1" to its value. 23 } 24 25 echo 26 27 while [ "$icount" -le "$ITERATIONS" ] 28 do 29 my_read var 30 echo "Entry #$icount = $var" 31 let "icount += 1" 32 echo 33 done 34 35 36 # Thanks to Stephane Chazelas for providing this instructive example. 37 38 exit 0</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="VARIABLELIST"><P><B><ANAME="EXITRETURN1"></A>Exit and Return</B></P><DL><DT><BCLASS="COMMAND">exit status</B></DT><DD><P>Functions return a value, called an <ICLASS="FIRSTTERM">exit status</I>. The exit status may be explicitly specified by a <BCLASS="COMMAND">return</B> statement, otherwise it is the exit status of the last command in the function (<SPANCLASS="RETURNVALUE">0</SPAN> if successful, and a non-zero error code if not). This <AHREF="exit-status.html#EXITSTATUSREF">exit status</A> may be used in the script by referencing it as <AHREF="variables2.html#XSTATVARREF">$?</A>. This mechanism effectively permits script functions to have a <SPANCLASS="QUOTE">"return value"</SPAN> similar to C functions.</P></DD><DT><BCLASS="COMMAND">return</B></DT><DD><P><ANAME="RETURNREF"></A></P><P>Terminates a function. A <BCLASS="COMMAND">return</B> command <ANAME="AEN17024"HREF="#FTN.AEN17024">[1]</A> optionally takes an <ICLASS="FIRSTTERM">integer</I> argument, which is returned to the calling script as the <SPANCLASS="QUOTE">"exit status"</SPAN> of the function, and this exit status is assigned to the variable <AHREF="variables2.html#XSTATVARREF">$?</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="MAX"></A><P><B>Example 23-7. Maximum of two numbers</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # max.sh: Maximum of two integers. 3 4 E_PARAM_ERR=250 # If less than 2 params passed to function. 5 EQUAL=251 # Return value if both params equal. 6 # Error values out of range of any 7 #+ params that might be fed to the function. 8 9 max2 () # Returns larger of two numbers. 10 { # Note: numbers compared must be less than 257. 11 if [ -z "$2" ] 12 then 13 return $E_PARAM_ERR 14 fi 15 16 if [ "$1" -eq "$2" ] 17 then 18 return $EQUAL 19 else 20 if [ "$1" -gt "$2" ] 21 then 22 return $1 23 else 24 return $2 25 fi 26 fi 27 } 28 29 max2 33 34 30 return_val=$? 31 32 if [ "$return_val" -eq $E_PARAM_ERR ] 33 then 34 echo "Need to pass two parameters to the function." 35 elif [ "$return_val" -eq $EQUAL ] 36 then 37 echo "The two numbers are equal." 38 else 39 echo "The larger of the two numbers is $return_val." 40 fi 41 42 43 exit 0 44 45 # Exercise (easy): 46 # --------------- 47 # Convert this to an interactive script, 48 #+ that is, have the script ask for input (two numbers).</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="TIP"><TABLECLASS="TIP"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/tip.png"HSPACE="5"ALT="Tip"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>For a function to return a string or array, use a dedicated variable. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 count_lines_in_etc_passwd() 2 { 3 [[ -r /etc/passwd ]] && REPLY=$(echo $(wc -l < /etc/passwd)) 4 # If /etc/passwd is readable, set REPLY to line count. 5 # Returns both a parameter value and status information. 6 # The 'echo' seems unnecessary, but . . . 7 #+ it removes excess whitespace from the output. 8 } 9 10 if count_lines_in_etc_passwd 11 then 12 echo "There are $REPLY lines in /etc/passwd." 13 else 14 echo "Cannot count lines in /etc/passwd." 15 fi 16 17 # Thanks, S.C.</PRE></TD></TR></TABLE> </P></TD></TR></TABLE></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX61"></A><P><B>Example 23-8. Converting numbers to Roman numerals</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 # Arabic number to Roman numeral conversion 4 # Range: 0 - 200 5 # It's crude, but it works. 6 7 # Extending the range and otherwise improving the script is left as an exercise. 8 9 # Usage: roman number-to-convert 10 11 LIMIT=200 12 E_ARG_ERR=65 13 E_OUT_OF_RANGE=66 14 15 if [ -z "$1" ] 16 then 17 echo "Usage: `basename $0` number-to-convert" 18 exit $E_ARG_ERR 19 fi 20 21 num=$1 22 if [ "$num" -gt $LIMIT ] 23 then 24 echo "Out of range!" 25 exit $E_OUT_OF_RANGE 26 fi 27 28 to_roman () # Must declare function before first call to it. 29 { 30 number=$1 31 factor=$2 32 rchar=$3 33 let "remainder = number - factor" 34 while [ "$remainder" -ge 0 ] 35 do 36 echo -n $rchar 37 let "number -= factor" 38 let "remainder = number - factor" 39 done 40 41 return $number 42 # Exercise: 43 # -------- 44 # Explain how this function works. 45 # Hint: division by successive subtraction. 46 } 47 48 49 to_roman $num 100 C 50 num=$? 51 to_roman $num 90 LXXXX 52 num=$? 53 to_roman $num 50 L 54 num=$? 55 to_roman $num 40 XL 56 num=$?
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -