750 lines
11 KiB
HTML
750 lines
11 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Bash, version 3</TITLE
|
|
><META
|
|
NAME="GENERATOR"
|
|
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK
|
|
REL="HOME"
|
|
TITLE="Advanced Bash-Scripting Guide"
|
|
HREF="index.html"><LINK
|
|
REL="UP"
|
|
TITLE="Bash, versions 2, 3, and 4"
|
|
HREF="bash2.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Bash, version 2"
|
|
HREF="bashver2.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Bash, version 4"
|
|
HREF="bashver4.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"
|
|
>Advanced Bash-Scripting Guide: </TH
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="left"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="bashver2.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
>Chapter 37. Bash, versions 2, 3, and 4</TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="bashver4.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="BASHVER3"
|
|
></A
|
|
>37.2. Bash, version 3</H1
|
|
><P
|
|
><A
|
|
NAME="BASH3REF"
|
|
></A
|
|
></P
|
|
><P
|
|
>On July 27, 2004, Chet Ramey released version 3 of Bash.
|
|
This update fixed quite a number of bugs and added new
|
|
features.</P
|
|
><P
|
|
>Some of the more important added features:
|
|
|
|
<P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
><A
|
|
NAME="BRACEEXPREF3"
|
|
></A
|
|
></P
|
|
><P
|
|
>A new, more generalized <B
|
|
CLASS="COMMAND"
|
|
>{a..z}</B
|
|
> <A
|
|
HREF="special-chars.html#BRACEEXPREF"
|
|
>brace expansion</A
|
|
> operator.</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
for i in {1..10}
|
|
# Simpler and more straightforward than
|
|
#+ for i in $(seq 10)
|
|
do
|
|
echo -n "$i "
|
|
done
|
|
|
|
echo
|
|
|
|
# 1 2 3 4 5 6 7 8 9 10
|
|
|
|
|
|
|
|
# Or just . . .
|
|
|
|
echo {a..z} # a b c d e f g h i j k l m n o p q r s t u v w x y z
|
|
echo {e..m} # e f g h i j k l m
|
|
echo {z..a} # z y x w v u t s r q p o n m l k j i h g f e d c b a
|
|
# Works backwards, too.
|
|
echo {25..30} # 25 26 27 28 29 30
|
|
echo {3..-2} # 3 2 1 0 -1 -2
|
|
echo {X..d} # X Y Z [ ] ^ _ ` a b c d
|
|
# Shows (some of) the ASCII characters between Z and a,
|
|
#+ but don't rely on this type of behavior because . . .
|
|
echo {]..a} # {]..a}
|
|
# Why?
|
|
|
|
|
|
# You can tack on prefixes and suffixes.
|
|
echo "Number #"{1..4}, "..."
|
|
# Number #1, Number #2, Number #3, Number #4, ...
|
|
|
|
|
|
# You can concatenate brace-expansion sets.
|
|
echo {1..3}{x..z}" +" "..."
|
|
# 1x + 1y + 1z + 2x + 2y + 2z + 3x + 3y + 3z + ...
|
|
# Generates an algebraic expression.
|
|
# This could be used to find permutations.
|
|
|
|
# You can nest brace-expansion sets.
|
|
echo {{a..c},{1..3}}
|
|
# a b c 1 2 3
|
|
# The "comma operator" splices together strings.
|
|
|
|
# ########## ######### ############ ########### ######### ###############
|
|
# Unfortunately, brace expansion does not lend itself to parameterization.
|
|
var1=1
|
|
var2=5
|
|
echo {$var1..$var2} # {1..5}
|
|
|
|
|
|
# Yet, as Emiliano G. points out, using "eval" overcomes this limitation.
|
|
|
|
start=0
|
|
end=10
|
|
for index in $(eval echo {$start..$end})
|
|
do
|
|
echo -n "$index " # 0 1 2 3 4 5 6 7 8 9 10
|
|
done
|
|
|
|
echo</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>The <B
|
|
CLASS="COMMAND"
|
|
>${!array[@]}</B
|
|
> operator, which
|
|
expands to all the indices of a given <A
|
|
HREF="arrays.html#ARRAYREF"
|
|
>array</A
|
|
>.</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
Array=(element-zero element-one element-two element-three)
|
|
|
|
echo ${Array[0]} # element-zero
|
|
# First element of array.
|
|
|
|
echo ${!Array[@]} # 0 1 2 3
|
|
# All the indices of Array.
|
|
|
|
for i in ${!Array[@]}
|
|
do
|
|
echo ${Array[i]} # element-zero
|
|
# element-one
|
|
# element-two
|
|
# element-three
|
|
#
|
|
# All the elements in Array.
|
|
done</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><A
|
|
NAME="REGEXMATCHREF"
|
|
></A
|
|
></P
|
|
><P
|
|
>The <B
|
|
CLASS="COMMAND"
|
|
>=~</B
|
|
> <A
|
|
HREF="regexp.html#REGEXREF"
|
|
>Regular
|
|
Expression</A
|
|
> matching operator within a <A
|
|
HREF="testconstructs.html#DBLBRACKETS"
|
|
>double brackets</A
|
|
> test expression.
|
|
(Perl has a similar operator.)</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
variable="This is a fine mess."
|
|
|
|
echo "$variable"
|
|
|
|
# Regex matching with =~ operator within [[ double brackets ]].
|
|
if [[ "$variable" =~ T.........fin*es* ]]
|
|
# NOTE: As of version 3.2 of Bash, expression to match no longer quoted.
|
|
then
|
|
echo "match found"
|
|
# match found
|
|
fi</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><P
|
|
>Or, more usefully:</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
input=$1
|
|
|
|
|
|
if [[ "$input" =~ "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]" ]]
|
|
# ^ NOTE: Quoting not necessary, as of version 3.2 of Bash.
|
|
# NNN-NN-NNNN (where each N is a digit).
|
|
then
|
|
echo "Social Security number."
|
|
# Process SSN.
|
|
else
|
|
echo "Not a Social Security number!"
|
|
# Or, ask for corrected input.
|
|
fi</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><P
|
|
>For additional examples of using the
|
|
<B
|
|
CLASS="COMMAND"
|
|
>=~</B
|
|
> operator, see <A
|
|
HREF="contributed-scripts.html#WHX"
|
|
>Example A-29</A
|
|
>,
|
|
<A
|
|
HREF="x17837.html#MAILBOXGREP"
|
|
>Example 19-14</A
|
|
>, <A
|
|
HREF="contributed-scripts.html#FINDSPLIT"
|
|
>Example A-35</A
|
|
>, and <A
|
|
HREF="contributed-scripts.html#TOHTML"
|
|
>Example A-24</A
|
|
>.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
><A
|
|
NAME="PIPEFAILREF"
|
|
></A
|
|
></P
|
|
><P
|
|
>The new <TT
|
|
CLASS="OPTION"
|
|
>set -o pipefail</TT
|
|
> option is
|
|
useful for debugging <A
|
|
HREF="special-chars.html#PIPEREF"
|
|
>pipes</A
|
|
>. If
|
|
this option is set, then the <A
|
|
HREF="exit-status.html#EXITSTATUSREF"
|
|
>exit status</A
|
|
> of a pipe
|
|
is the exit status of the last command in the pipe to
|
|
<EM
|
|
>fail</EM
|
|
> (return a non-zero value), rather
|
|
than the actual final command in the pipe.</P
|
|
><P
|
|
>See <A
|
|
HREF="communications.html#FC4UPD"
|
|
>Example 16-43</A
|
|
>.</P
|
|
></LI
|
|
></UL
|
|
>
|
|
</P
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="100%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="../images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>The update to version 3 of Bash breaks a few scripts
|
|
that worked under earlier versions. <EM
|
|
>Test critical legacy
|
|
scripts to make sure they still work!</EM
|
|
></P
|
|
><P
|
|
>As it happens, a couple of the scripts in the
|
|
<EM
|
|
>Advanced Bash Scripting Guide</EM
|
|
> had to be
|
|
fixed up (see <A
|
|
HREF="internalvariables.html#TOUT"
|
|
>Example 9-4</A
|
|
>, for instance).</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN20956"
|
|
></A
|
|
>37.2.1. Bash, version 3.1</H2
|
|
><P
|
|
>The version 3.1 update of Bash introduces a number of bugfixes
|
|
and a few minor changes.</P
|
|
><P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>The <SPAN
|
|
CLASS="TOKEN"
|
|
>+=</SPAN
|
|
> operator is now permitted in
|
|
in places where previously only the <SPAN
|
|
CLASS="TOKEN"
|
|
>=</SPAN
|
|
>
|
|
assignment operator was recognized.</P
|
|
><P
|
|
><A
|
|
NAME="PLUSEQSTR"
|
|
></A
|
|
></P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>a=1
|
|
echo $a # 1
|
|
|
|
a+=5 # Won't work under versions of Bash earlier than 3.1.
|
|
echo $a # 15
|
|
|
|
a+=Hello
|
|
echo $a # 15Hello</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Here, <SPAN
|
|
CLASS="TOKEN"
|
|
>+=</SPAN
|
|
> functions as a <I
|
|
CLASS="FIRSTTERM"
|
|
>string
|
|
concatenation</I
|
|
> operator. Note that its behavior
|
|
in this particular context is different than within a
|
|
<A
|
|
HREF="internal.html#LETREF"
|
|
>let</A
|
|
> construct.</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>a=1
|
|
echo $a # 1
|
|
|
|
let a+=5 # Integer arithmetic, rather than string concatenation.
|
|
echo $a # 6
|
|
|
|
let a+=Hello # Doesn't "add" anything to a.
|
|
echo $a # 6</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
><A
|
|
NAME="PATHAPPEND"
|
|
></A
|
|
>Jeffrey Haemer points out
|
|
that this concatenation operator can be quite
|
|
useful. In this instance, we append a directory to the
|
|
<TT
|
|
CLASS="VARNAME"
|
|
>$PATH</TT
|
|
>.</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="1"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
><TT
|
|
CLASS="PROMPT"
|
|
>bash$ </TT
|
|
><TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>echo $PATH</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="COMPUTEROUTPUT"
|
|
>/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin/:/usr/games</TT
|
|
>
|
|
|
|
|
|
<TT
|
|
CLASS="PROMPT"
|
|
>bash$ </TT
|
|
><TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>PATH+=:/opt/bin</B
|
|
></TT
|
|
>
|
|
|
|
<TT
|
|
CLASS="PROMPT"
|
|
>bash$ </TT
|
|
><TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>echo $PATH</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="COMPUTEROUTPUT"
|
|
>/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin/:/usr/games:/opt/bin</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
|
|
</P
|
|
></LI
|
|
></UL
|
|
></DIV
|
|
><DIV
|
|
CLASS="SECT2"
|
|
><H2
|
|
CLASS="SECT2"
|
|
><A
|
|
NAME="AEN20987"
|
|
></A
|
|
>37.2.2. Bash, version 3.2</H2
|
|
><P
|
|
>This is pretty much a bugfix update.</P
|
|
><P
|
|
></P
|
|
><UL
|
|
><LI
|
|
><P
|
|
>In <A
|
|
HREF="parameter-substitution.html#PSGLOB"
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>global</I
|
|
>
|
|
parameter substitutions</A
|
|
>, the pattern no longer anchors
|
|
at the start of the string.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>The <TT
|
|
CLASS="OPTION"
|
|
>--wordexp</TT
|
|
> option disables
|
|
<A
|
|
HREF="process-sub.html#PROCESSSUBREF"
|
|
>process substitution</A
|
|
>.</P
|
|
></LI
|
|
><LI
|
|
><P
|
|
>The <B
|
|
CLASS="COMMAND"
|
|
>=~</B
|
|
> <A
|
|
HREF="bashver3.html#REGEXMATCHREF"
|
|
>Regular Expression
|
|
match operator</A
|
|
> no longer requires
|
|
<A
|
|
HREF="quoting.html#QUOTINGREF"
|
|
>quoting</A
|
|
> of the
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>pattern</I
|
|
> within <A
|
|
HREF="testconstructs.html#DBLBRACKETS"
|
|
>[[ ... ]]</A
|
|
>.</P
|
|
><DIV
|
|
CLASS="CAUTION"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="CAUTION"
|
|
WIDTH="90%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="../images/caution.gif"
|
|
HSPACE="5"
|
|
ALT="Caution"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>In fact, quoting in this context is
|
|
<EM
|
|
>not</EM
|
|
> advisable as it may
|
|
cause <I
|
|
CLASS="FIRSTTERM"
|
|
>regex</I
|
|
> evaluation to fail.
|
|
Chet Ramey states in the <A
|
|
HREF="biblio.html#BASHFAQ"
|
|
>Bash
|
|
FAQ</A
|
|
> that quoting explicitly disables regex evaluation.
|
|
See also the <A
|
|
HREF="https://bugs.launchpad.net/ubuntu-website/+bug/109931"
|
|
TARGET="_top"
|
|
> Ubuntu Bug List</A
|
|
> and <A
|
|
HREF="http://en.wikinerds.org/index.php/Bash_syntax_and_semantics"
|
|
TARGET="_top"
|
|
> Wikinerds on Bash syntax</A
|
|
>.</P
|
|
><P
|
|
>Setting <EM
|
|
>shopt -s compat31</EM
|
|
>
|
|
in a script causes reversion to the original
|
|
behavior.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></LI
|
|
></UL
|
|
></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="bashver2.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="bashver4.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Bash, version 2</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="bash2.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Bash, version 4</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |