📄 functions.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><HTML><HEAD><TITLE>Functions</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="Advanced Bash-Scripting Guide"HREF="index.html"><LINKREL="UP"TITLE="Advanced Topics"HREF="part5.html"><LINKREL="PREVIOUS"TITLE="Process Substitution"HREF="process-sub.html"><LINKREL="NEXT"TITLE="Local Variables"HREF="localvar.html"><METAHTTP-EQUIV="Content-Style-Type"CONTENT="text/css"><LINKREL="stylesheet"HREF="common/kde-common.css"TYPE="text/css"><METAHTTP-EQUIV="Content-Type"CONTENT="text/html; charset=iso-8859-1"><METAHTTP-EQUIV="Content-Language"CONTENT="en"><LINKREL="stylesheet"HREF="common/kde-localised.css"TYPE="text/css"TITLE="KDE-English"><LINKREL="stylesheet"HREF="common/kde-default.css"TYPE="text/css"TITLE="KDE-Default"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#AA0000"VLINK="#AA0055"ALINK="#AA0000"STYLE="font-family: sans-serif;"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="process-sub.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="localvar.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1><ANAME="FUNCTIONS"></A>Chapter 23. Functions</H1><P><ANAME="FUNCTIONREF"></A></P><P>Like <SPANCLASS="QUOTE">"real"</SPAN> programming languages, Bash has functions, though in a somewhat limited implementation. A function is a subroutine, a <AHREF="special-chars.html#CODEBLOCKREF">code block</A> that implements a set of operations, a <SPANCLASS="QUOTE">"black box"</SPAN> that performs a specified task. Wherever there is repetitive code, when a task repeats with only slight variations in procedure, then consider using a function.</P><P><P><BCLASS="COMMAND">function</B> <TTCLASS="REPLACEABLE"><I>function_name</I></TT> { <BR> <TTCLASS="REPLACEABLE"><I>command</I></TT>... <BR> } <BR></P> or <P> <TTCLASS="REPLACEABLE"><I>function_name</I></TT> () { <BR> <TTCLASS="REPLACEABLE"><I>command</I></TT>... <BR> } <BR></P> </P><P>This second form will cheer the hearts of C programmers (and is more portable).</P><P>As in C, the function's opening bracket may optionally appear on the second line.</P><P><P> <TTCLASS="REPLACEABLE"><I>function_name</I></TT> () <BR> { <BR> <TTCLASS="REPLACEABLE"><I>command</I></TT>... <BR> } <BR></P> </P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>A function may be <SPANCLASS="QUOTE">"compacted"</SPAN> into a single line.</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 fun () { echo "This is a function"; echo; }</PRE></TD></TR></TABLE></P><P>In this case, however, a <ICLASS="FIRSTTERM">semicolon</I> must follow the final command in the function.</P><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 fun () { echo "This is a function"; echo } # Error!</PRE></TD></TR></TABLE></P></TD></TR></TABLE></DIV><P>Functions are called, <ICLASS="FIRSTTERM">triggered</I>, simply by invoking their names.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX59"></A><P><B>Example 23-1. Simple functions</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 JUST_A_SECOND=1 4 5 funky () 6 { # This is about as simple as functions get. 7 echo "This is a funky function." 8 echo "Now exiting funky function." 9 } # Function declaration must precede call. 10 11 12 fun () 13 { # A somewhat more complex function. 14 i=0 15 REPEATS=30 16 17 echo 18 echo "And now the fun really begins." 19 echo 20 21 sleep $JUST_A_SECOND # Hey, wait a second! 22 while [ $i -lt $REPEATS ] 23 do 24 echo "----------FUNCTIONS---------->" 25 echo "<------------ARE-------------" 26 echo "<------------FUN------------>" 27 echo 28 let "i+=1" 29 done 30 } 31 32 # Now, call the functions. 33 34 funky 35 fun 36 37 exit 0</PRE></TD></TR></TABLE><HR></DIV><P><ANAME="FUNCTDEFMUST"></A></P><P>The function definition must precede the first call to it. There is no method of <SPANCLASS="QUOTE">"declaring"</SPAN> the function, as, for example, in C. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 f1 2 # Will give an error message, since function "f1" not yet defined. 3 4 declare -f f1 # This doesn't help either. 5 f1 # Still an error message. 6 7 # However... 8 9 10 f1 () 11 { 12 echo "Calling function \"f2\" from within function \"f1\"." 13 f2 14 } 15 16 f2 () 17 { 18 echo "Function \"f2\"." 19 } 20 21 f1 # Function "f2" is not actually called until this point, 22 #+ although it is referenced before its definition. 23 # This is permissible. 24 25 # Thanks, S.C.</PRE></TD></TR></TABLE> </P><P>It is even possible to nest a function within another function, although this is not very useful. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 f1 () 2 { 3 4 f2 () # nested 5 { 6 echo "Function \"f2\", inside \"f1\"." 7 } 8 9 } 10 11 f2 # Gives an error message. 12 # Even a preceding "declare -f f2" wouldn't help. 13 14 echo 15 16 f1 # Does nothing, since calling "f1" does not automatically call "f2". 17 f2 # Now, it's all right to call "f2", 18 #+ since its definition has been made visible by calling "f1". 19 20 # Thanks, S.C.</PRE></TD></TR></TABLE> </P><P>Function declarations can appear in unlikely places, even where a command would otherwise go. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 ls -l | foo() { echo "foo"; } # Permissible, but useless. 2 3 4 5 if [ "$USER" = bozo ] 6 then 7 bozo_greet () # Function definition embedded in an if/then construct. 8 { 9 echo "Hello, Bozo." 10 } 11 fi 12 13 bozo_greet # Works only for Bozo, and other users get an error. 14 15 16 17 # Something like this might be useful in some contexts. 18 NO_EXIT=1 # Will enable function definition below. 19 20 [[ $NO_EXIT -eq 1 ]] && exit() { true; } # Function definition in an "and-list". 21 # If $NO_EXIT is 1, declares "exit ()". 22 # This disables the "exit" builtin by aliasing it to "true". 23 24 exit # Invokes "exit ()" function, not "exit" builtin. 25 26 27 28 # Or, similarly: 29 filename=file1 30 31 [ -f "$filename" ] && 32 foo () { rm -f "$filename"; echo "File "$filename" deleted."; } || 33 foo () { echo "File "$filename" not found."; touch bar; } 34 35 foo 36 37 # Thanks, S.C. and Christopher Head</PRE></TD></TR></TABLE> </P><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>What happens when different versions of the same function appear in a script? <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 # As Yan Chen points out, 2 # when a function is defined multiple times, 3 # the final version is what is invoked. 4 # This is not, however, particularly useful. 5 6 func () 7 { 8 echo "First version of func ()." 9 } 10 11 func () 12 { 13 echo "Second version of func ()." 14 } 15 16 func # Second version of func (). 17 18 exit $? 19 20 # It is even possible to use functions to override 21 #+ or preempt system commands. 22 # Of course, this is *not* advisable.</PRE></TD></TR></TABLE></P></TD></TR></TABLE></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="COMPLEXFUNCT"></A>23.1. Complex Functions and Function Complexities</H1><P>Functions may process arguments passed to them and return an <AHREF="exit-status.html#EXITSTATUSREF">exit status</A> to the script for further processing.</P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 function_name $arg1 $arg2</PRE></TD></TR></TABLE><P><ANAME="PASSEDARGS"></A></P><P>The function refers to the passed arguments by position (as if they were <AHREF="variables2.html#POSPARAMREF">positional parameters</A>), that is, <TTCLASS="VARNAME">$1</TT>, <TTCLASS="VARNAME">$2</TT>, and so forth.</P><DIVCLASS="EXAMPLE"><HR><ANAME="EX60"></A><P><B>Example 23-2. Function Taking Parameters</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # Functions and parameters 3 4 DEFAULT=default # Default param value. 5 6 func2 () { 7 if [ -z "$1" ] # Is parameter #1 zero length? 8 then 9 echo "-Parameter #1 is zero length.-" # Or no parameter passed. 10 else 11 echo "-Param #1 is \"$1\".-" 12 fi 13 14 variable=${1-$DEFAULT} # What does 15 echo "variable = $variable" #+ parameter substitution show? 16 # --------------------------- 17 # It distinguishes between 18 #+ no param and a null param. 19 20 if [ "$2" ] 21 then 22 echo "-Parameter #2 is \"$2\".-" 23 fi 24 25 return 0 26 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -