⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 functions.html

📁 Shall高级编程
💻 HTML
📖 第 1 页 / 共 3 页
字号:
  57&nbsp;to_roman $num 10 X  58&nbsp;num=$?  59&nbsp;to_roman $num 9 IX  60&nbsp;num=$?  61&nbsp;to_roman $num 5 V  62&nbsp;num=$?  63&nbsp;to_roman $num 4 IV  64&nbsp;num=$?  65&nbsp;to_roman $num 1 I  66&nbsp;  67&nbsp;echo  68&nbsp;  69&nbsp;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>, which accounts for this particular	      limitation.  Fortunately, there are various <AHREF="assortedtips.html#RVT">workarounds</A> for those situations	      requiring a large integer return value from a	      function.</P><DIVCLASS="EXAMPLE"><HR><ANAME="RETURNTEST"></A><P><B>Example 23-9. Testing large return values in a function</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# return-test.sh   3&nbsp;   4&nbsp;# The largest positive value a function can return is 255.   5&nbsp;   6&nbsp;return_test ()         # Returns whatever passed to it.   7&nbsp;{   8&nbsp;  return $1   9&nbsp;}  10&nbsp;  11&nbsp;return_test 27         # o.k.  12&nbsp;echo $?                # Returns 27.  13&nbsp;    14&nbsp;return_test 255        # Still o.k.  15&nbsp;echo $?                # Returns 255.  16&nbsp;  17&nbsp;return_test 257        # Error!  18&nbsp;echo $?                # Returns 1 (return code for miscellaneous error).  19&nbsp;  20&nbsp;# ======================================================  21&nbsp;return_test -151896    # Do large negative numbers work?  22&nbsp;echo $?                # Will this return -151896?  23&nbsp;                       # No! It returns 168.  24&nbsp;#  Version of Bash before 2.05b permitted  25&nbsp;#+ large negative integer return values.  26&nbsp;#  Newer versions of Bash plug this loophole.  27&nbsp;#  This may break older scripts.  28&nbsp;#  Caution!  29&nbsp;# ======================================================  30&nbsp;  31&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>A workaround for obtaining large integer <SPANCLASS="QUOTE">"return	      values"</SPAN> is to simply assign the <SPANCLASS="QUOTE">"return	      value"</SPAN> to a global variable.	        <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;Return_Val=   # Global variable to hold oversize return value of function.   2&nbsp;   3&nbsp;alt_return_test ()   4&nbsp;{   5&nbsp;  fvar=$1   6&nbsp;  Return_Val=$fvar   7&nbsp;  return   # Returns 0 (success).   8&nbsp;}   9&nbsp;  10&nbsp;alt_return_test 1  11&nbsp;echo $?                              # 0  12&nbsp;echo "return value = $Return_Val"    # 1  13&nbsp;  14&nbsp;alt_return_test 256  15&nbsp;echo "return value = $Return_Val"    # 256  16&nbsp;  17&nbsp;alt_return_test 257  18&nbsp;echo "return value = $Return_Val"    # 257  19&nbsp;  20&nbsp;alt_return_test 25701  21&nbsp;echo "return value = $Return_Val"    #25701</PRE></TD></TR></TABLE>            </P><P><ANAME="CAPTURERETVAL"></A></P><P>A more elegant method is to have the function              <BCLASS="COMMAND">echo</B> its <SPANCLASS="QUOTE">"return              value to <TTCLASS="FILENAME">stdout</TT>,"</SPAN> and              then capture it by <AHREF="commandsub.html#COMMANDSUBREF">command	      substitution</A>. See the <AHREF="assortedtips.html#RVT">discussion	      of this</A> in <AHREF="assortedtips.html">Section 33.8</A>.</P><DIVCLASS="EXAMPLE"><HR><ANAME="MAX2"></A><P><B>Example 23-10. Comparing two large integers</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# max2.sh: Maximum of two LARGE integers.   3&nbsp;   4&nbsp;#  This is the previous "max.sh" example,   5&nbsp;#+ modified to permit comparing large integers.   6&nbsp;   7&nbsp;EQUAL=0             # Return value if both params equal.   8&nbsp;E_PARAM_ERR=-99999  # Not enough params passed to function.   9&nbsp;#           ^^^^^^    Out of range of any params that might be passed.  10&nbsp;  11&nbsp;max2 ()             # "Returns" larger of two numbers.  12&nbsp;{  13&nbsp;if [ -z "$2" ]  14&nbsp;then  15&nbsp;  echo $E_PARAM_ERR  16&nbsp;  return  17&nbsp;fi  18&nbsp;  19&nbsp;if [ "$1" -eq "$2" ]  20&nbsp;then  21&nbsp;  echo $EQUAL  22&nbsp;  return  23&nbsp;else  24&nbsp;  if [ "$1" -gt "$2" ]  25&nbsp;  then  26&nbsp;    retval=$1  27&nbsp;  else  28&nbsp;    retval=$2  29&nbsp;  fi  30&nbsp;fi  31&nbsp;  32&nbsp;echo $retval        # Echoes (to stdout), rather than returning value.  33&nbsp;                    # Why?  34&nbsp;}  35&nbsp;  36&nbsp;  37&nbsp;return_val=$(max2 33001 33997)  38&nbsp;#            ^^^^             Function name  39&nbsp;#                 ^^^^^ ^^^^^ Params passed  40&nbsp;#  This is actually a form of command substitution:  41&nbsp;#+ treating a function as if it were a command,  42&nbsp;#+ and assigning the stdout of the function to the variable "return_val."  43&nbsp;  44&nbsp;  45&nbsp;# ========================= OUTPUT ========================  46&nbsp;if [ "$return_val" -eq "$E_PARAM_ERR" ]  47&nbsp;  then  48&nbsp;  echo "Error in parameters passed to comparison function!"  49&nbsp;elif [ "$return_val" -eq "$EQUAL" ]  50&nbsp;  then  51&nbsp;    echo "The two numbers are equal."  52&nbsp;else  53&nbsp;    echo "The larger of the two numbers is $return_val."  54&nbsp;fi  55&nbsp;# =========================================================  56&nbsp;    57&nbsp;exit 0  58&nbsp;  59&nbsp;#  Exercises:  60&nbsp;#  ---------  61&nbsp;#  1) Find a more elegant way of testing  62&nbsp;#+    the parameters passed to the function.  63&nbsp;#  2) Simplify the if/then structure at "OUTPUT."  64&nbsp;#  3) Rewrite the script to take input from command-line parameters.</PRE></TD></TR></TABLE><HR></DIV><P>Here is another example of capturing a function	      <SPANCLASS="QUOTE">"return value."</SPAN> Understanding it requires some	      knowledge of <AHREF="awk.html#AWKREF">awk</A>.	    <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;month_length ()  # Takes month number as an argument.   2&nbsp;{                # Returns number of days in month.   3&nbsp;monthD="31 28 31 30 31 30 31 31 30 31 30 31"  # Declare as local?   4&nbsp;echo "$monthD" | awk '{ print $'"${1}"' }'    # Tricky.   5&nbsp;#                             ^^^^^^^^^   6&nbsp;# Parameter passed to function  ($1 -- month number), then to awk.   7&nbsp;# Awk sees this as "print $1 . . . print $12" (depending on month number)   8&nbsp;# Template for passing a parameter to embedded awk script:   9&nbsp;#                                 $'"${script_parameter}"'  10&nbsp;  11&nbsp;#  Needs error checking for correct parameter range (1-12)  12&nbsp;#+ and for February in leap year.  13&nbsp;}  14&nbsp;  15&nbsp;# ----------------------------------------------  16&nbsp;# Usage example:  17&nbsp;month=4        # April, for example (4th month).  18&nbsp;days_in=$(month_length $month)  19&nbsp;echo $days_in  # 30  20&nbsp;# ----------------------------------------------</PRE></TD></TR></TABLE></P><P>See also <AHREF="contributed-scripts.html#DAYSBETWEEN">Example A-7</A>.</P><P><TTCLASS="USERINPUT"><B>Exercise:</B></TT> Using what we have	      just learned, extend the previous <AHREF="functions.html#EX61">Roman numerals example</A> to accept	      arbitrarily large input.</P></TD></TR></TABLE></DIV></DD></DL></DIV><DIVCLASS="VARIABLELIST"><P><B><ANAME="REDSTDINFUNC1"></A>Redirection</B></P><DL><DT><TTCLASS="REPLACEABLE"><I>Redirecting the stdin	    of a function</I></TT></DT><DD><P>A function is essentially a <AHREF="special-chars.html#CODEBLOCKREF">code block</A>, which means its	      <TTCLASS="FILENAME">stdin</TT> can be redirected (as in <AHREF="special-chars.html#EX8">Example 3-1</A>).</P><DIVCLASS="EXAMPLE"><HR><ANAME="REALNAME"></A><P><B>Example 23-11. Real name from username</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;#!/bin/bash   2&nbsp;# realname.sh   3&nbsp;#   4&nbsp;# From username, gets "real name" from /etc/passwd.   5&nbsp;   6&nbsp;   7&nbsp;ARGCOUNT=1       # Expect one arg.   8&nbsp;E_WRONGARGS=65   9&nbsp;  10&nbsp;file=/etc/passwd  11&nbsp;pattern=$1  12&nbsp;  13&nbsp;if [ $# -ne "$ARGCOUNT" ]  14&nbsp;then  15&nbsp;  echo "Usage: `basename $0` USERNAME"  16&nbsp;  exit $E_WRONGARGS  17&nbsp;fi    18&nbsp;  19&nbsp;file_excerpt ()  # Scan file for pattern, then print relevant portion of line.  20&nbsp;{  21&nbsp;while read line  # "while" does not necessarily need "[ condition ]"  22&nbsp;do  23&nbsp;  echo "$line" | grep $1 | awk -F":" '{ print $5 }'  # Have awk use ":" delimiter.  24&nbsp;done  25&nbsp;} &#60;$file  # Redirect into function's stdin.  26&nbsp;  27&nbsp;file_excerpt $pattern  28&nbsp;  29&nbsp;# Yes, this entire script could be reduced to  30&nbsp;#       grep PATTERN /etc/passwd | awk -F":" '{ print $5 }'  31&nbsp;# or  32&nbsp;#       awk -F: '/PATTERN/ {print $5}'  33&nbsp;# or  34&nbsp;#       awk -F: '($1 == "username") { print $5 }' # real name from username  35&nbsp;# However, it might not be as instructive.  36&nbsp;  37&nbsp;exit 0</PRE></TD></TR></TABLE><HR></DIV><P>There is an alternate, and perhaps less confusing	     method of redirecting a function's	     <TTCLASS="FILENAME">stdin</TT>.  This involves redirecting the	     <TTCLASS="FILENAME">stdin</TT> to an embedded bracketed code	     block within the function.	       <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING">   1&nbsp;# Instead of:   2&nbsp;Function ()   3&nbsp;{   4&nbsp; ...   5&nbsp; } &#60; file   6&nbsp;   7&nbsp;# Try this:   8&nbsp;Function ()   9&nbsp;{  10&nbsp;  {  11&nbsp;    ...  12&nbsp;   } &#60; file  13&nbsp;}  14&nbsp;  15&nbsp;# Similarly,  16&nbsp;  17&nbsp;Function ()  # This works.  18&nbsp;{  19&nbsp;  {  20&nbsp;   echo $*  21&nbsp;  } | tr a b  22&nbsp;}  23&nbsp;  24&nbsp;Function ()  # This doesn't work.  25&nbsp;{  26&nbsp;  echo $*  27&nbsp;} | tr a b   # A nested code block is mandatory here.  28&nbsp;  29&nbsp;  30&nbsp;# Thanks, S.C.</PRE></TD></TR></TABLE>           </P></DD></DL></DIV></DIV></DIV><H3CLASS="FOOTNOTES">Notes</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN17024"HREF="functions.html#AEN17024">[1]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>The <BCLASS="COMMAND">return</B> command is a		 Bash <AHREF="internal.html#BUILTINREF">builtin</A>.</P></TD></TR></TABLE><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="process-sub.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="localvar.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Process Substitution</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part5.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Local Variables</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -