1470 lines
20 KiB
HTML
1470 lines
20 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<HTML
|
|
><HEAD
|
|
><TITLE
|
|
>Operators</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="Operations and Related Topics"
|
|
HREF="operations.html"><LINK
|
|
REL="PREVIOUS"
|
|
TITLE="Operations and Related Topics"
|
|
HREF="operations.html"><LINK
|
|
REL="NEXT"
|
|
TITLE="Numerical Constants"
|
|
HREF="numerical-constants.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="operations.html"
|
|
ACCESSKEY="P"
|
|
>Prev</A
|
|
></TD
|
|
><TD
|
|
WIDTH="80%"
|
|
ALIGN="center"
|
|
VALIGN="bottom"
|
|
>Chapter 8. Operations and Related Topics</TD
|
|
><TD
|
|
WIDTH="10%"
|
|
ALIGN="right"
|
|
VALIGN="bottom"
|
|
><A
|
|
HREF="numerical-constants.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><HR
|
|
ALIGN="LEFT"
|
|
WIDTH="100%"></DIV
|
|
><DIV
|
|
CLASS="SECT1"
|
|
><H1
|
|
CLASS="SECT1"
|
|
><A
|
|
NAME="OPS"
|
|
></A
|
|
>8.1. Operators</H1
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><P
|
|
><B
|
|
><A
|
|
NAME="ASNOP1"
|
|
></A
|
|
>assignment</B
|
|
></P
|
|
><DL
|
|
><DT
|
|
><TT
|
|
CLASS="REPLACEABLE"
|
|
><I
|
|
>variable assignment</I
|
|
></TT
|
|
></DT
|
|
><DD
|
|
><P
|
|
>Initializing or changing the value of a variable</P
|
|
></DD
|
|
><DT
|
|
>=</DT
|
|
><DD
|
|
><P
|
|
>All-purpose assignment operator, which works for both
|
|
arithmetic and string assignments.</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>var=27
|
|
category=minerals # No spaces allowed after the "=".</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</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
|
|
>Do not confuse the <SPAN
|
|
CLASS="QUOTE"
|
|
>"="</SPAN
|
|
> assignment
|
|
operator with the <A
|
|
HREF="comparison-ops.html#EQUALSIGNREF"
|
|
>= test
|
|
operator</A
|
|
>.</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
># = as a test operator
|
|
|
|
if [ "$string1" = "$string2" ]
|
|
then
|
|
command
|
|
fi
|
|
|
|
# if [ "X$string1" = "X$string2" ] is safer,
|
|
#+ to prevent an error message should one of the variables be empty.
|
|
# (The prepended "X" characters cancel out.)</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><P
|
|
><B
|
|
><A
|
|
NAME="AROPS1"
|
|
></A
|
|
>arithmetic operators</B
|
|
></P
|
|
><DL
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>+</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>plus</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>-</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>minus</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>*</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>multiplication</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>/</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>division</P
|
|
></DD
|
|
><DT
|
|
><A
|
|
NAME="EXPONENTIATIONREF"
|
|
></A
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>**</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>exponentiation</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
># Bash, version 2.02, introduced the "**" exponentiation operator.
|
|
|
|
let "z=5**3" # 5 * 5 * 5
|
|
echo "z = $z" # z = 125</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></DD
|
|
><DT
|
|
><A
|
|
NAME="MODULOREF"
|
|
></A
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>%</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>modulo, or mod (returns the
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>remainder</I
|
|
> of an integer division
|
|
operation)</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
|
|
>expr 5 % 3</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="COMPUTEROUTPUT"
|
|
>2</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
<EM
|
|
>5/3 = 1, with remainder 2</EM
|
|
>
|
|
</P
|
|
><P
|
|
>This operator finds use in, among other things,
|
|
generating numbers within a specific range (see <A
|
|
HREF="randomvar.html#EX21"
|
|
>Example 9-11</A
|
|
> and <A
|
|
HREF="randomvar.html#RANDOMTEST"
|
|
>Example 9-15</A
|
|
>) and
|
|
formatting program output (see <A
|
|
HREF="arrays.html#QFUNCTION"
|
|
>Example 27-16</A
|
|
> and
|
|
<A
|
|
HREF="contributed-scripts.html#COLLATZ"
|
|
>Example A-6</A
|
|
>). It can even be used to generate
|
|
prime numbers, (see <A
|
|
HREF="contributed-scripts.html#PRIMES"
|
|
>Example A-15</A
|
|
>). Modulo turns
|
|
up surprisingly often in numerical recipes.</P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="GCD"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 8-1. Greatest common divisor</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
# gcd.sh: greatest common divisor
|
|
# Uses Euclid's algorithm
|
|
|
|
# The "greatest common divisor" (gcd) of two integers
|
|
#+ is the largest integer that will divide both, leaving no remainder.
|
|
|
|
# Euclid's algorithm uses successive division.
|
|
# In each pass,
|
|
#+ dividend <--- divisor
|
|
#+ divisor <--- remainder
|
|
#+ until remainder = 0.
|
|
# The gcd = dividend, on the final pass.
|
|
#
|
|
# For an excellent discussion of Euclid's algorithm, see
|
|
#+ Jim Loy's site, http://www.jimloy.com/number/euclids.htm.
|
|
|
|
|
|
# ------------------------------------------------------
|
|
# Argument check
|
|
ARGS=2
|
|
E_BADARGS=85
|
|
|
|
if [ $# -ne "$ARGS" ]
|
|
then
|
|
echo "Usage: `basename $0` first-number second-number"
|
|
exit $E_BADARGS
|
|
fi
|
|
# ------------------------------------------------------
|
|
|
|
|
|
gcd ()
|
|
{
|
|
|
|
dividend=$1 # Arbitrary assignment.
|
|
divisor=$2 #! It doesn't matter which of the two is larger.
|
|
# Why not?
|
|
|
|
remainder=1 # If an uninitialized variable is used inside
|
|
#+ test brackets, an error message results.
|
|
|
|
until [ "$remainder" -eq 0 ]
|
|
do # ^^^^^^^^^^ Must be previously initialized!
|
|
let "remainder = $dividend % $divisor"
|
|
dividend=$divisor # Now repeat with 2 smallest numbers.
|
|
divisor=$remainder
|
|
done # Euclid's algorithm
|
|
|
|
} # Last $dividend is the gcd.
|
|
|
|
|
|
gcd $1 $2
|
|
|
|
echo; echo "GCD of $1 and $2 = $dividend"; echo
|
|
|
|
|
|
# Exercises :
|
|
# ---------
|
|
# 1) Check command-line arguments to make sure they are integers,
|
|
#+ and exit the script with an appropriate error message if not.
|
|
# 2) Rewrite the gcd () function to use local variables.
|
|
|
|
exit 0</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DD
|
|
><DT
|
|
><A
|
|
NAME="ARITHOPSCOMB"
|
|
></A
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>+=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>plus-equal</I
|
|
> (increment variable
|
|
by a constant)
|
|
|
|
<A
|
|
NAME="AEN3907"
|
|
HREF="#FTN.AEN3907"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
>
|
|
|
|
</P
|
|
><P
|
|
><TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>let "var += 5"</B
|
|
></TT
|
|
> results in
|
|
<TT
|
|
CLASS="PARAMETER"
|
|
><I
|
|
>var</I
|
|
></TT
|
|
> being incremented by
|
|
<TT
|
|
CLASS="LITERAL"
|
|
>5</TT
|
|
>.</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>-=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>minus-equal</I
|
|
> (decrement
|
|
variable by a constant)</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>*=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>times-equal</I
|
|
> (multiply
|
|
variable by a constant)</P
|
|
><P
|
|
><TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>let "var *= 4"</B
|
|
></TT
|
|
> results in <TT
|
|
CLASS="PARAMETER"
|
|
><I
|
|
>var</I
|
|
></TT
|
|
>
|
|
being multiplied by <TT
|
|
CLASS="LITERAL"
|
|
>4</TT
|
|
>.</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>/=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>slash-equal</I
|
|
> (divide
|
|
variable by a constant)</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>%=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>mod-equal</I
|
|
>
|
|
(<I
|
|
CLASS="FIRSTTERM"
|
|
>remainder</I
|
|
>
|
|
of dividing variable by a constant)</P
|
|
><P
|
|
><EM
|
|
>Arithmetic operators often occur in an
|
|
<A
|
|
HREF="moreadv.html#EXPRREF"
|
|
>expr</A
|
|
> or <A
|
|
HREF="internal.html#LETREF"
|
|
>let</A
|
|
> expression.</EM
|
|
></P
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="ARITHOPS"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 8-2. Using Arithmetic Operations</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
# Counting to 11 in 10 different ways.
|
|
|
|
n=1; echo -n "$n "
|
|
|
|
let "n = $n + 1" # let "n = n + 1" also works.
|
|
echo -n "$n "
|
|
|
|
|
|
: $((n = $n + 1))
|
|
# ":" necessary because otherwise Bash attempts
|
|
#+ to interpret "$((n = $n + 1))" as a command.
|
|
echo -n "$n "
|
|
|
|
(( n = n + 1 ))
|
|
# A simpler alternative to the method above.
|
|
# Thanks, David Lombard, for pointing this out.
|
|
echo -n "$n "
|
|
|
|
n=$(($n + 1))
|
|
echo -n "$n "
|
|
|
|
: $[ n = $n + 1 ]
|
|
# ":" necessary because otherwise Bash attempts
|
|
#+ to interpret "$[ n = $n + 1 ]" as a command.
|
|
# Works even if "n" was initialized as a string.
|
|
echo -n "$n "
|
|
|
|
n=$[ $n + 1 ]
|
|
# Works even if "n" was initialized as a string.
|
|
#* Avoid this type of construct, since it is obsolete and nonportable.
|
|
# Thanks, Stephane Chazelas.
|
|
echo -n "$n "
|
|
|
|
# Now for C-style increment operators.
|
|
# Thanks, Frank Wang, for pointing this out.
|
|
|
|
let "n++" # let "++n" also works.
|
|
echo -n "$n "
|
|
|
|
(( n++ )) # (( ++n )) also works.
|
|
echo -n "$n "
|
|
|
|
: $(( n++ )) # : $(( ++n )) also works.
|
|
echo -n "$n "
|
|
|
|
: $[ n++ ] # : $[ ++n ] also works
|
|
echo -n "$n "
|
|
|
|
echo
|
|
|
|
exit 0</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
><P
|
|
><A
|
|
NAME="INTVARREF"
|
|
></A
|
|
></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
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>Integer variables in older versions of Bash were signed
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>long</I
|
|
> (32-bit) integers, in the range of
|
|
-2147483648 to 2147483647. An operation that took a variable
|
|
outside these limits gave an erroneous result.</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>echo $BASH_VERSION # 1.14
|
|
|
|
a=2147483646
|
|
echo "a = $a" # a = 2147483646
|
|
let "a+=1" # Increment "a".
|
|
echo "a = $a" # a = 2147483647
|
|
let "a+=1" # increment "a" again, past the limit.
|
|
echo "a = $a" # a = -2147483648
|
|
# ERROR: out of range,
|
|
# + and the leftmost bit, the sign bit,
|
|
# + has been set, making the result negative.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>As of version >= 2.05b, Bash supports 64-bit integers.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><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
|
|
><A
|
|
NAME="NOFLOATINGPOINT"
|
|
></A
|
|
></P
|
|
><P
|
|
>Bash does not understand floating point arithmetic. It
|
|
treats numbers containing a decimal point as strings.</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>a=1.5
|
|
|
|
let "b = $a + 1.3" # Error.
|
|
# t2.sh: let: b = 1.5 + 1.3: syntax error in expression
|
|
# (error token is ".5 + 1.3")
|
|
|
|
echo "b = $b" # b=1</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>Use <A
|
|
HREF="mathc.html#BCREF"
|
|
>bc</A
|
|
> in scripts that that need floating
|
|
point calculations or math library functions.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="FORMALPARA"
|
|
><P
|
|
><B
|
|
>bitwise operators. </B
|
|
>The bitwise operators seldom make an appearance in shell scripts.
|
|
Their chief use seems to be manipulating and testing values read
|
|
from ports or <A
|
|
HREF="devref1.html#SOCKETREF"
|
|
>sockets</A
|
|
>. <SPAN
|
|
CLASS="QUOTE"
|
|
>"Bit
|
|
flipping"</SPAN
|
|
> is more relevant to compiled languages, such
|
|
as C and C++, which provide direct access to system
|
|
hardware. However, see <EM
|
|
>vladz's</EM
|
|
>
|
|
ingenious use of bitwise operators in his
|
|
<I
|
|
CLASS="FIRSTTERM"
|
|
>base64.sh</I
|
|
> (<A
|
|
HREF="contributed-scripts.html#BASE64"
|
|
>Example A-54</A
|
|
>)
|
|
script. </P
|
|
></DIV
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><P
|
|
><B
|
|
><A
|
|
NAME="BITWSOPS1"
|
|
></A
|
|
>bitwise operators</B
|
|
></P
|
|
><DL
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
><<</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise left shift (multiplies by <TT
|
|
CLASS="LITERAL"
|
|
>2</TT
|
|
>
|
|
for each shift position)</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
><<=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>left-shift-equal</I
|
|
></P
|
|
><P
|
|
><TT
|
|
CLASS="USERINPUT"
|
|
><B
|
|
>let "var <<= 2"</B
|
|
></TT
|
|
> results in <TT
|
|
CLASS="PARAMETER"
|
|
><I
|
|
>var</I
|
|
></TT
|
|
>
|
|
left-shifted <TT
|
|
CLASS="LITERAL"
|
|
>2</TT
|
|
> bits (multiplied by <TT
|
|
CLASS="LITERAL"
|
|
>4</TT
|
|
>)</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>>></SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise right shift (divides by <TT
|
|
CLASS="LITERAL"
|
|
>2</TT
|
|
>
|
|
for each shift position)</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>>>=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>right-shift-equal</I
|
|
>
|
|
(inverse of <SPAN
|
|
CLASS="TOKEN"
|
|
><<=</SPAN
|
|
>)</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>&</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise AND</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>&=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise <I
|
|
CLASS="FIRSTTERM"
|
|
>AND-equal</I
|
|
></P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>|</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise OR</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>|=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise <I
|
|
CLASS="FIRSTTERM"
|
|
>OR-equal</I
|
|
></P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>~</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise NOT</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>^</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise XOR</P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>^=</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>bitwise <I
|
|
CLASS="FIRSTTERM"
|
|
>XOR-equal</I
|
|
></P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><P
|
|
><B
|
|
><A
|
|
NAME="LOGOPS1"
|
|
></A
|
|
>logical (boolean) operators</B
|
|
></P
|
|
><DL
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>!</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>NOT</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>if [ ! -f $FILENAME ]
|
|
then
|
|
...</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
></DD
|
|
><DT
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>&&</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>AND</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>if [ $condition1 ] && [ $condition2 ]
|
|
# Same as: if [ $condition1 -a $condition2 ]
|
|
# Returns true if both condition1 and condition2 hold true...
|
|
|
|
if [[ $condition1 && $condition2 ]] # Also works.
|
|
# Note that && operator not permitted <EM
|
|
>inside brackets</EM
|
|
>
|
|
#+ of [ ... ] construct.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="90%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="../images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>&&</SPAN
|
|
> may also be used, depending on context,
|
|
in an <A
|
|
HREF="list-cons.html#LISTCONSREF"
|
|
>and list</A
|
|
>
|
|
to concatenate commands.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DD
|
|
><DT
|
|
><A
|
|
NAME="ORREF"
|
|
></A
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>||</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>OR</P
|
|
><P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>if [ $condition1 ] || [ $condition2 ]
|
|
# Same as: if [ $condition1 -o $condition2 ]
|
|
# Returns true if either condition1 or condition2 holds true...
|
|
|
|
if [[ $condition1 || $condition2 ]] # Also works.
|
|
# Note that || operator not permitted <EM
|
|
>inside brackets</EM
|
|
>
|
|
#+ of a [ ... ] construct.</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></P
|
|
><DIV
|
|
CLASS="NOTE"
|
|
><P
|
|
></P
|
|
><TABLE
|
|
CLASS="NOTE"
|
|
WIDTH="90%"
|
|
BORDER="0"
|
|
><TR
|
|
><TD
|
|
WIDTH="25"
|
|
ALIGN="CENTER"
|
|
VALIGN="TOP"
|
|
><IMG
|
|
SRC="../images/note.gif"
|
|
HSPACE="5"
|
|
ALT="Note"></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
><P
|
|
>Bash tests the <A
|
|
HREF="exit-status.html#EXITSTATUSREF"
|
|
>exit
|
|
status</A
|
|
> of each statement linked with a logical
|
|
operator.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><DIV
|
|
CLASS="EXAMPLE"
|
|
><A
|
|
NAME="ANDOR"
|
|
></A
|
|
><P
|
|
><B
|
|
>Example 8-3. Compound Condition Tests Using && and ||</B
|
|
></P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>#!/bin/bash
|
|
|
|
a=24
|
|
b=47
|
|
|
|
if [ "$a" -eq 24 ] && [ "$b" -eq 47 ]
|
|
then
|
|
echo "Test #1 succeeds."
|
|
else
|
|
echo "Test #1 fails."
|
|
fi
|
|
|
|
# ERROR: if [ "$a" -eq 24 && "$b" -eq 47 ]
|
|
#+ attempts to execute ' [ "$a" -eq 24 '
|
|
#+ and fails to finding matching ']'.
|
|
#
|
|
# Note: if [[ $a -eq 24 && $b -eq 24 ]] works.
|
|
# The double-bracket if-test is more flexible
|
|
#+ than the single-bracket version.
|
|
# (The "&&" has a different meaning in line 17 than in line 6.)
|
|
# Thanks, Stephane Chazelas, for pointing this out.
|
|
|
|
|
|
if [ "$a" -eq 98 ] || [ "$b" -eq 47 ]
|
|
then
|
|
echo "Test #2 succeeds."
|
|
else
|
|
echo "Test #2 fails."
|
|
fi
|
|
|
|
|
|
# The -a and -o options provide
|
|
#+ an alternative compound condition test.
|
|
# Thanks to Patrick Callahan for pointing this out.
|
|
|
|
|
|
if [ "$a" -eq 24 -a "$b" -eq 47 ]
|
|
then
|
|
echo "Test #3 succeeds."
|
|
else
|
|
echo "Test #3 fails."
|
|
fi
|
|
|
|
|
|
if [ "$a" -eq 98 -o "$b" -eq 47 ]
|
|
then
|
|
echo "Test #4 succeeds."
|
|
else
|
|
echo "Test #4 fails."
|
|
fi
|
|
|
|
|
|
a=rhino
|
|
b=crocodile
|
|
if [ "$a" = rhino ] && [ "$b" = crocodile ]
|
|
then
|
|
echo "Test #5 succeeds."
|
|
else
|
|
echo "Test #5 fails."
|
|
fi
|
|
|
|
exit 0</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
><P
|
|
>The <SPAN
|
|
CLASS="TOKEN"
|
|
>&&</SPAN
|
|
> and <SPAN
|
|
CLASS="TOKEN"
|
|
>||</SPAN
|
|
> operators also
|
|
find use in an arithmetic context.</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 $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0))</B
|
|
></TT
|
|
>
|
|
<TT
|
|
CLASS="COMPUTEROUTPUT"
|
|
>1 0 1 0</TT
|
|
>
|
|
</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><P
|
|
><B
|
|
><A
|
|
NAME="MISCOP1"
|
|
></A
|
|
>miscellaneous operators</B
|
|
></P
|
|
><DL
|
|
><DT
|
|
><A
|
|
NAME="COMMAOP"
|
|
></A
|
|
><SPAN
|
|
CLASS="TOKEN"
|
|
>,</SPAN
|
|
></DT
|
|
><DD
|
|
><P
|
|
>Comma operator</P
|
|
><P
|
|
>The <B
|
|
CLASS="COMMAND"
|
|
>comma operator</B
|
|
> chains together
|
|
two or more arithmetic operations. All the operations are
|
|
evaluated (with possible <I
|
|
CLASS="FIRSTTERM"
|
|
>side
|
|
effects</I
|
|
>.
|
|
<A
|
|
NAME="AEN4242"
|
|
HREF="#FTN.AEN4242"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[2]</SPAN
|
|
></A
|
|
>
|
|
</P
|
|
><P
|
|
> <TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="90%"
|
|
><TR
|
|
><TD
|
|
><FONT
|
|
COLOR="#000000"
|
|
><PRE
|
|
CLASS="PROGRAMLISTING"
|
|
>let "t1 = ((5 + 3, 7 - 1, 15 - 4))"
|
|
echo "t1 = $t1" ^^^^^^ # t1 = 11
|
|
# Here t1 is set to the result of the last operation. Why?
|
|
|
|
let "t2 = ((a = 9, 15 / 3))" # Set "a" and calculate "t2".
|
|
echo "t2 = $t2 a = $a" # t2 = 5 a = 9</PRE
|
|
></FONT
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
>
|
|
</P
|
|
><P
|
|
>The comma operator finds use mainly in <A
|
|
HREF="loops1.html#FORLOOPREF1"
|
|
>for loops</A
|
|
>. See <A
|
|
HREF="loops1.html#FORLOOPC"
|
|
>Example 11-13</A
|
|
>.</P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
></DIV
|
|
><H3
|
|
CLASS="FOOTNOTES"
|
|
>Notes</H3
|
|
><TABLE
|
|
BORDER="0"
|
|
CLASS="FOOTNOTES"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN3907"
|
|
HREF="ops.html#AEN3907"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[1]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
>In a different context, <B
|
|
CLASS="COMMAND"
|
|
>+=</B
|
|
> can
|
|
serve as a <I
|
|
CLASS="FIRSTTERM"
|
|
>string concatenation</I
|
|
>
|
|
operator. This can be useful for <A
|
|
HREF="bashver3.html#PATHAPPEND"
|
|
>modifying <I
|
|
CLASS="FIRSTTERM"
|
|
>environmental
|
|
variables</I
|
|
></A
|
|
>.</P
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="5%"
|
|
><A
|
|
NAME="FTN.AEN4242"
|
|
HREF="ops.html#AEN4242"
|
|
><SPAN
|
|
CLASS="footnote"
|
|
>[2]</SPAN
|
|
></A
|
|
></TD
|
|
><TD
|
|
ALIGN="LEFT"
|
|
VALIGN="TOP"
|
|
WIDTH="95%"
|
|
><P
|
|
><I
|
|
CLASS="FIRSTTERM"
|
|
>Side effects</I
|
|
>
|
|
are, of course, unintended -- and usually undesirable --
|
|
consequences.</P
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><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="operations.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="numerical-constants.html"
|
|
ACCESSKEY="N"
|
|
>Next</A
|
|
></TD
|
|
></TR
|
|
><TR
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="left"
|
|
VALIGN="top"
|
|
>Operations and Related Topics</TD
|
|
><TD
|
|
WIDTH="34%"
|
|
ALIGN="center"
|
|
VALIGN="top"
|
|
><A
|
|
HREF="operations.html"
|
|
ACCESSKEY="U"
|
|
>Up</A
|
|
></TD
|
|
><TD
|
|
WIDTH="33%"
|
|
ALIGN="right"
|
|
VALIGN="top"
|
|
>Numerical Constants</TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></BODY
|
|
></HTML
|
|
> |