📄 functions.html
字号:
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 pointers), if passed as parameters to functions, will be treated as string literals. <ICLASS="EMPHASIS">Functions interpret their arguments literally.</I></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 <ICLASS="EMPHASIS">after</I> 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="AEN14191"HREF="#FTN.AEN14191">[1]</A> optionally takes an <ICLASS="EMPHASIS">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=-198 # If less than 2 params passed to function. 5 EQUAL=-199 # 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=$? 57 to_roman $num 10 X 58 num=$? 59 to_roman $num 9 IX 60 num=$? 61 to_roman $num 5 V 62 num=$? 63 to_roman $num 4 IV 64 num=$? 65 to_roman $num 1 I 66 67 echo 68 69 exit 0</PRE></TD></TR></TABLE><HR></DIV><P>See also <AHREF="testbranch.html#ISALPHA">Example 10-28</A>.</P><DIVCLASS="IMPORTANT"><TABLECLASS="IMPORTANT"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/important.png"HSPACE="5"ALT="Important"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>The largest positive integer a function can return is 255. The <BCLASS="COMMAND">return</B> command is closely tied to the concept of <AHREF="exit-status.html#EXITSTATUSREF">exit status</A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -