541 lines
9.6 KiB
HTML
541 lines
9.6 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Introduction</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Bash Guide for Beginners"
|
|
HREF="index.html"><LINK
|
|
REL="UP"
|
|
TITLE="Functions"
|
|
HREF="chap_11.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Functions"
|
|
HREF="chap_11.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Examples of functions in scripts"
|
|
HREF="sect_11_02.html"></HEAD
|
|
><BODY
|
|
CLASS="sect1"
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#840084"
|
|
ALINK="#0000FF"
|
|
><DIV
|
|
CLASS="NAVHEADER"
|
|
><TABLE
|
|
SUMMARY="Header navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TH
|
|
COLSPAN="3"
|
|
ALIGN="center"
|
|
>Bash Guide for Beginners</TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="chap_11.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
>Chapter 11. Functions</TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="sect_11_02.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="sect1"
|
|
><H1
|
|
CLASS="sect1"
|
|
><A
|
|
NAME="sect_11_01"
|
|
></A
|
|
>11.1. Introduction</H1
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="sect_11_01_01"
|
|
></A
|
|
>11.1.1. What are functions?</H2
|
|
><P
|
|
>Shell functions are a way to group commands for later execution, using a single name for this group, or <EM
|
|
>routine</EM
|
|
>. The name of the routine must be unique within the shell or script. All the commands that make up a function are executed like regular commands. When calling on a function as a simple command name, the list of commands associated with that function name is executed. A function is executed within the shell in which it has been declared: no new process is created to interpret the commands.</P
|
|
><P
|
|
>Special built-in commands are found before shell functions during command lookup. The special built-ins are: <B
|
|
CLASS="command"
|
|
>break</B
|
|
>, <B
|
|
CLASS="command"
|
|
>:</B
|
|
>, <B
|
|
CLASS="command"
|
|
>.</B
|
|
>, <B
|
|
CLASS="command"
|
|
>continue</B
|
|
>, <B
|
|
CLASS="command"
|
|
>eval</B
|
|
>, <B
|
|
CLASS="command"
|
|
>exec</B
|
|
>, <B
|
|
CLASS="command"
|
|
>exit</B
|
|
>, <B
|
|
CLASS="command"
|
|
>export</B
|
|
>, <B
|
|
CLASS="command"
|
|
>readonly</B
|
|
>, <B
|
|
CLASS="command"
|
|
>return</B
|
|
>, <B
|
|
CLASS="command"
|
|
>set</B
|
|
>, <B
|
|
CLASS="command"
|
|
>shift</B
|
|
>, <B
|
|
CLASS="command"
|
|
>trap</B
|
|
> and <B
|
|
CLASS="command"
|
|
>unset</B
|
|
>.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="sect_11_01_02"
|
|
></A
|
|
>11.1.2. Function syntax</H2
|
|
><P
|
|
>Functions either use the syntax</P
|
|
><P
|
|
><B
|
|
CLASS="command"
|
|
>function FUNCTION { COMMANDS; }</B
|
|
> </P
|
|
><P
|
|
>or</P
|
|
><P
|
|
><B
|
|
CLASS="command"
|
|
>FUNCTION () { COMMANDS; }</B
|
|
> </P
|
|
><P
|
|
>Both define a shell function <B
|
|
CLASS="command"
|
|
>FUNCTION</B
|
|
>. The use of the built-in command <B
|
|
CLASS="command"
|
|
>function</B
|
|
> is optional; however, if it is not used, parentheses are needed.</P
|
|
><P
|
|
>The commands listed between curly braces make up the body of the function. These commands are executed whenever <B
|
|
CLASS="command"
|
|
>FUNCTION</B
|
|
> is specified as the name of a command. The exit status is the exit status of the last command executed in the body.</P
|
|
><DIV
|
|
CLASS="note"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="note"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="../images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TH
|
|
ALIGN="LEFT"
|
|
VALIGN="CENTER"
|
|
><B
|
|
>Common mistakes</B
|
|
></TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
> </TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>The curly braces must be separated from the body by spaces, otherwise they are interpreted in the wrong way.</P
|
|
><P
|
|
>The body of a function should end in a semicolon or a newline.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="sect_11_01_03"
|
|
></A
|
|
>11.1.3. Positional parameters in functions</H2
|
|
><P
|
|
>Functions are like mini-scripts: they can accept parameters, they can use variables only known within the function (using the <B
|
|
CLASS="command"
|
|
>local</B
|
|
> shell built-in) and they can return values to the calling shell.</P
|
|
><P
|
|
>A function also has a system for interpreting positional parameters. However, the positional parameters passed to a function are not the same as the ones passed to a command or script.</P
|
|
><P
|
|
>When a function is executed, the arguments to the function become the positional parameters during its execution. The special parameter <TT
|
|
CLASS="varname"
|
|
>#</TT
|
|
> that expands to the number of positional parameters is updated to reflect the change. Positional parameter <TT
|
|
CLASS="varname"
|
|
>0</TT
|
|
> is unchanged. The Bash variable <TT
|
|
CLASS="varname"
|
|
>FUNCNAME</TT
|
|
> is set to the name of the function, while it is executing.</P
|
|
><P
|
|
>If the <B
|
|
CLASS="command"
|
|
>return</B
|
|
> built-in is executed in a function, the function completes and execution resumes with the next command after the function call. When a function completes, the values of the positional parameters and the special parameter <TT
|
|
CLASS="varname"
|
|
>#</TT
|
|
> are restored to the values they had prior to the function's execution. If a numeric argument is given to <B
|
|
CLASS="command"
|
|
>return</B
|
|
>, that status is returned. A simple example:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="screen"
|
|
> <TT
|
|
CLASS="prompt"
|
|
>[lydia@cointreau ~/test]</TT
|
|
> <B
|
|
CLASS="command"
|
|
>cat <TT
|
|
CLASS="filename"
|
|
>showparams.sh</TT
|
|
></B
|
|
>
|
|
#!/bin/bash
|
|
|
|
echo "This script demonstrates function arguments."
|
|
echo
|
|
|
|
echo "Positional parameter 1 for the script is $1."
|
|
echo
|
|
|
|
test ()
|
|
{
|
|
echo "Positional parameter 1 in the function is $1."
|
|
RETURN_VALUE=$?
|
|
echo "The exit code of this function is $RETURN_VALUE."
|
|
}
|
|
|
|
test other_param
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
>[lydia@cointreau ~/test]</TT
|
|
> <B
|
|
CLASS="command"
|
|
>./showparams.sh <TT
|
|
CLASS="parameter"
|
|
><I
|
|
>parameter1</I
|
|
></TT
|
|
></B
|
|
>
|
|
This script demonstrates function arguments.
|
|
|
|
Positional parameter 1 for the script is parameter1.
|
|
|
|
Positional parameter 1 in the function is other_param.
|
|
The exit code of this function is 0.
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
>[lydia@cointreau ~/test]</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Note that the return value or exit code of the function is often storen in a variable, so that it can be probed at a later point. The init scripts on your system often use the technique of probing the <TT
|
|
CLASS="varname"
|
|
>RETVAL</TT
|
|
> variable in a conditional test, like this one:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="screen"
|
|
> <B
|
|
CLASS="command"
|
|
>if <TT
|
|
CLASS="parameter"
|
|
><I
|
|
>[ $RETVAL -eq 0 ]</I
|
|
></TT
|
|
>; then
|
|
<start the daemon></B
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>Or like this example from the <TT
|
|
CLASS="filename"
|
|
>/etc/init.d/amd</TT
|
|
> script, where Bash's optimization features are used:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="screen"
|
|
> <B
|
|
CLASS="command"
|
|
><TT
|
|
CLASS="parameter"
|
|
><I
|
|
>[ $RETVAL = 0 ]</I
|
|
></TT
|
|
> && touch <TT
|
|
CLASS="filename"
|
|
>/var/lock/subsys/amd</TT
|
|
></B
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>The commands after <B
|
|
CLASS="command"
|
|
>&&</B
|
|
> are only executed when the test proves to be true; this is a shorter way to represent an <B
|
|
CLASS="command"
|
|
>if/then/fi</B
|
|
> structure.</P
|
|
><P
|
|
>The return code of the function is often used as exit code of the entire script. You'll see a lot of initscripts ending in something like <B
|
|
CLASS="command"
|
|
>exit <TT
|
|
CLASS="varname"
|
|
>$RETVAL</TT
|
|
></B
|
|
>.</P
|
|
></DIV
|
|
><DIV
|
|
CLASS="sect2"
|
|
><H2
|
|
CLASS="sect2"
|
|
><A
|
|
NAME="sect_11_01_04"
|
|
></A
|
|
>11.1.4. Displaying functions</H2
|
|
><P
|
|
>All functions known by the current shell can be displayed using the <B
|
|
CLASS="command"
|
|
>set</B
|
|
> built-in without options. Functions are retained after they are used, unless they are <B
|
|
CLASS="command"
|
|
>unset</B
|
|
> after use. The <B
|
|
CLASS="command"
|
|
>which</B
|
|
> command also displays functions:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="screen"
|
|
> <TT
|
|
CLASS="prompt"
|
|
>[lydia@cointreau ~]</TT
|
|
> <B
|
|
CLASS="command"
|
|
>which <TT
|
|
CLASS="filename"
|
|
>zless</TT
|
|
></B
|
|
>
|
|
zless is a function
|
|
zless ()
|
|
{
|
|
zcat "$@" | "$PAGER"
|
|
}
|
|
|
|
<TT
|
|
CLASS="prompt"
|
|
>[lydia@cointreau ~]</TT
|
|
> <B
|
|
CLASS="command"
|
|
>echo <TT
|
|
CLASS="varname"
|
|
>$PAGER</TT
|
|
></B
|
|
>
|
|
less
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
>This is the sort of function that is typically configured in the user's shell resource configuration files. Functions are more flexible than aliases and provide a simple and easy way of adapting the user environment.</P
|
|
><P
|
|
>Here's one for DOS users:</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="screen"
|
|
> dir ()
|
|
{
|
|
ls -F --color=auto -lF --color=always "$@" | less -r
|
|
}
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="NAVFOOTER"
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"><TABLE
|
|
SUMMARY="Footer navigation table"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
CELLPADDING="0"
|
|
CELLSPACING="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="chap_11.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="index.html"
|
|
ACCESSKEY="H"
|
|
>Home</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="sect_11_02.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Functions</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="chap_11.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Examples of functions in scripts</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |