1217 lines
16 KiB
HTML
1217 lines
16 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|||
|
<HTML
|
|||
|
><HEAD
|
|||
|
><TITLE
|
|||
|
>Other Comparison 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="Tests"
|
|||
|
HREF="tests.html"><LINK
|
|||
|
REL="PREVIOUS"
|
|||
|
TITLE="File test operators"
|
|||
|
HREF="fto.html"><LINK
|
|||
|
REL="NEXT"
|
|||
|
TITLE="Nested if/then Condition Tests"
|
|||
|
HREF="nestedifthen.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="fto.html"
|
|||
|
ACCESSKEY="P"
|
|||
|
>Prev</A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="80%"
|
|||
|
ALIGN="center"
|
|||
|
VALIGN="bottom"
|
|||
|
>Chapter 7. Tests</TD
|
|||
|
><TD
|
|||
|
WIDTH="10%"
|
|||
|
ALIGN="right"
|
|||
|
VALIGN="bottom"
|
|||
|
><A
|
|||
|
HREF="nestedifthen.html"
|
|||
|
ACCESSKEY="N"
|
|||
|
>Next</A
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
><HR
|
|||
|
ALIGN="LEFT"
|
|||
|
WIDTH="100%"></DIV
|
|||
|
><DIV
|
|||
|
CLASS="SECT1"
|
|||
|
><H1
|
|||
|
CLASS="SECT1"
|
|||
|
><A
|
|||
|
NAME="COMPARISON-OPS"
|
|||
|
></A
|
|||
|
>7.3. Other Comparison Operators</H1
|
|||
|
><P
|
|||
|
>A <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>binary</I
|
|||
|
> comparison operator
|
|||
|
compares two variables or quantities. <EM
|
|||
|
>Note
|
|||
|
that integer and string comparison use a different set of
|
|||
|
operators.</EM
|
|||
|
></P
|
|||
|
><P
|
|||
|
></P
|
|||
|
><DIV
|
|||
|
CLASS="VARIABLELIST"
|
|||
|
><P
|
|||
|
><B
|
|||
|
><A
|
|||
|
NAME="ICOMPARISON1"
|
|||
|
></A
|
|||
|
>integer comparison</B
|
|||
|
></P
|
|||
|
><DL
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="EQUALREF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-eq</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" -eq "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="NEQUALREF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-ne</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is not equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" -ne "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="GT0REF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-gt</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is greater than</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" -gt "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="GE0REF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-ge</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is greater than or equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" -ge "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="LT0REF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-lt</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is less than</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" -lt "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="LE0REF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-le</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is less than or equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" -le "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="INTLT"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
><</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is less than (within <A
|
|||
|
HREF="dblparens.html"
|
|||
|
>double
|
|||
|
parentheses</A
|
|||
|
>)</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>(("$a" < "$b"))</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="LTEQ"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
><=</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is less than or equal to (within double parentheses)</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>(("$a" <= "$b"))</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="INTGT"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>></SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is greater than (within double parentheses)</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>(("$a" > "$b"))</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="GTEQ"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>>=</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is greater than or equal to (within double parentheses)</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>(("$a" >= "$b"))</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
></DD
|
|||
|
></DL
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
></P
|
|||
|
><DIV
|
|||
|
CLASS="VARIABLELIST"
|
|||
|
><P
|
|||
|
><B
|
|||
|
><A
|
|||
|
NAME="SCOMPARISON1"
|
|||
|
></A
|
|||
|
>string comparison</B
|
|||
|
></P
|
|||
|
><DL
|
|||
|
><DT
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>=</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
><A
|
|||
|
NAME="EQUALSIGNREF"
|
|||
|
></A
|
|||
|
></P
|
|||
|
><P
|
|||
|
>is equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" = "$b" ]</B
|
|||
|
></TT
|
|||
|
></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
|
|||
|
>Note the <A
|
|||
|
HREF="special-chars.html#WHITESPACEREF"
|
|||
|
>whitespace</A
|
|||
|
>
|
|||
|
framing the <B
|
|||
|
CLASS="COMMAND"
|
|||
|
>=</B
|
|||
|
>.</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a"="$b" ]</B
|
|||
|
></TT
|
|||
|
> is
|
|||
|
<EM
|
|||
|
>not</EM
|
|||
|
> equivalent to the
|
|||
|
above.</P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="SCOMPARISON2"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>==</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" == "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
><P
|
|||
|
>This is a synonym for <SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>=</SPAN
|
|||
|
>.</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
|
|||
|
> The <SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>==</SPAN
|
|||
|
> comparison operator behaves differently
|
|||
|
within a <A
|
|||
|
HREF="testconstructs.html#DBLBRACKETS"
|
|||
|
>double-brackets</A
|
|||
|
>
|
|||
|
test than within single brackets.
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="90%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>[[ $a == z* ]] # True if $a starts with an "z" (pattern matching).
|
|||
|
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
|
|||
|
|
|||
|
[ $a == z* ] # File globbing and word splitting take place.
|
|||
|
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).
|
|||
|
|
|||
|
# Thanks, St<53>phane Chazelas</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="NOTEQUAL"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>!=</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is not equal to</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" != "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
><P
|
|||
|
>This operator uses pattern matching within a <A
|
|||
|
HREF="testconstructs.html#DBLBRACKETS"
|
|||
|
>[[ ... ]]</A
|
|||
|
> construct.</P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="LTREF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
><</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is less than, in <A
|
|||
|
HREF="special-chars.html#ASCIIDEF"
|
|||
|
>ASCII</A
|
|||
|
> alphabetical
|
|||
|
order</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [[ "$a" < "$b" ]]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" \< "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
><P
|
|||
|
>Note that the <SPAN
|
|||
|
CLASS="QUOTE"
|
|||
|
>"<"</SPAN
|
|||
|
> needs to be
|
|||
|
<A
|
|||
|
HREF="escapingsection.html#ESCP"
|
|||
|
>escaped</A
|
|||
|
> within a
|
|||
|
<TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>[ ]</B
|
|||
|
></TT
|
|||
|
> construct.</P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="GTREF"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>></SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>is greater than, in ASCII alphabetical order</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [[ "$a" > "$b" ]]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>if [ "$a" \> "$b" ]</B
|
|||
|
></TT
|
|||
|
></P
|
|||
|
><P
|
|||
|
>Note that the <SPAN
|
|||
|
CLASS="QUOTE"
|
|||
|
>">"</SPAN
|
|||
|
> needs to be
|
|||
|
escaped within a <TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>[ ]</B
|
|||
|
></TT
|
|||
|
> construct.</P
|
|||
|
><P
|
|||
|
>See <A
|
|||
|
HREF="arrays.html#BUBBLE"
|
|||
|
>Example 27-11</A
|
|||
|
> for an application of this
|
|||
|
comparison operator.</P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="STRINGNULL"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-z</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>string is <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>null</I
|
|||
|
>,
|
|||
|
that is, has zero length</P
|
|||
|
><P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="90%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
> String='' # Zero-length ("null") string variable.
|
|||
|
|
|||
|
if [ -z "$String" ]
|
|||
|
then
|
|||
|
echo "\$String is null."
|
|||
|
else
|
|||
|
echo "\$String is NOT null."
|
|||
|
fi # $String is null.</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="STRINGNOTNULL"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-n</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>string is not <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>null.</I
|
|||
|
></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
|
|||
|
>The <TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>-n</B
|
|||
|
></TT
|
|||
|
> test
|
|||
|
requires that the string be quoted within the
|
|||
|
test brackets. Using an unquoted string with
|
|||
|
<I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>! -z</I
|
|||
|
>, or even just the
|
|||
|
unquoted string alone within test brackets (see <A
|
|||
|
HREF="comparison-ops.html#STRTEST"
|
|||
|
>Example 7-6</A
|
|||
|
>) normally works, however, this is
|
|||
|
an unsafe practice. <EM
|
|||
|
>Always</EM
|
|||
|
> quote
|
|||
|
a tested string.
|
|||
|
<A
|
|||
|
NAME="AEN3669"
|
|||
|
HREF="#FTN.AEN3669"
|
|||
|
><SPAN
|
|||
|
CLASS="footnote"
|
|||
|
>[1]</SPAN
|
|||
|
></A
|
|||
|
>
|
|||
|
</P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
></DD
|
|||
|
></DL
|
|||
|
></DIV
|
|||
|
><DIV
|
|||
|
CLASS="EXAMPLE"
|
|||
|
><A
|
|||
|
NAME="EX13"
|
|||
|
></A
|
|||
|
><P
|
|||
|
><B
|
|||
|
>Example 7-5. Arithmetic and string comparisons</B
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>#!/bin/bash
|
|||
|
|
|||
|
a=4
|
|||
|
b=5
|
|||
|
|
|||
|
# Here "a" and "b" can be treated either as integers or strings.
|
|||
|
# There is some blurring between the arithmetic and string comparisons,
|
|||
|
#+ since Bash variables are not strongly typed.
|
|||
|
|
|||
|
# Bash permits integer operations and comparisons on variables
|
|||
|
#+ whose value consists of all-integer characters.
|
|||
|
# Caution advised, however.
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
if [ "$a" -ne "$b" ]
|
|||
|
then
|
|||
|
echo "$a is not equal to $b"
|
|||
|
echo "(arithmetic comparison)"
|
|||
|
fi
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
if [ "$a" != "$b" ]
|
|||
|
then
|
|||
|
echo "$a is not equal to $b."
|
|||
|
echo "(string comparison)"
|
|||
|
# "4" != "5"
|
|||
|
# ASCII 52 != ASCII 53
|
|||
|
fi
|
|||
|
|
|||
|
# In this particular instance, both "-ne" and "!=" work.
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
exit 0</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><DIV
|
|||
|
CLASS="EXAMPLE"
|
|||
|
><A
|
|||
|
NAME="STRTEST"
|
|||
|
></A
|
|||
|
><P
|
|||
|
><B
|
|||
|
>Example 7-6. Testing whether a string is <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>null</I
|
|||
|
></B
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>#!/bin/bash
|
|||
|
# str-test.sh: Testing null strings and unquoted strings,
|
|||
|
#+ but not strings and sealing wax, not to mention cabbages and kings . . .
|
|||
|
|
|||
|
# Using if [ ... ]
|
|||
|
|
|||
|
# If a string has not been initialized, it has no defined value.
|
|||
|
# This state is called "null" (not the same as zero!).
|
|||
|
|
|||
|
if [ -n $string1 ] # string1 has not been declared or initialized.
|
|||
|
then
|
|||
|
echo "String \"string1\" is not null."
|
|||
|
else
|
|||
|
echo "String \"string1\" is null."
|
|||
|
fi # Wrong result.
|
|||
|
# Shows $string1 as not null, although it was not initialized.
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
# Let's try it again.
|
|||
|
|
|||
|
if [ -n "$string1" ] # This time, $string1 is quoted.
|
|||
|
then
|
|||
|
echo "String \"string1\" is not null."
|
|||
|
else
|
|||
|
echo "String \"string1\" is null."
|
|||
|
fi # Quote strings within test brackets!
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
if [ $string1 ] # This time, $string1 stands naked.
|
|||
|
then
|
|||
|
echo "String \"string1\" is not null."
|
|||
|
else
|
|||
|
echo "String \"string1\" is null."
|
|||
|
fi # This works fine.
|
|||
|
# The [ ... ] test operator alone detects whether the string is null.
|
|||
|
# However it is good practice to quote it (if [ "$string1" ]).
|
|||
|
#
|
|||
|
# As Stephane Chazelas points out,
|
|||
|
# if [ $string1 ] has one argument, "]"
|
|||
|
# if [ "$string1" ] has two arguments, the empty "$string1" and "]"
|
|||
|
|
|||
|
|
|||
|
echo
|
|||
|
|
|||
|
|
|||
|
string1=initialized
|
|||
|
|
|||
|
if [ $string1 ] # Again, $string1 stands unquoted.
|
|||
|
then
|
|||
|
echo "String \"string1\" is not null."
|
|||
|
else
|
|||
|
echo "String \"string1\" is null."
|
|||
|
fi # Again, gives correct result.
|
|||
|
# Still, it is better to quote it ("$string1"), because . . .
|
|||
|
|
|||
|
|
|||
|
string1="a = b"
|
|||
|
|
|||
|
if [ $string1 ] # Again, $string1 stands unquoted.
|
|||
|
then
|
|||
|
echo "String \"string1\" is not null."
|
|||
|
else
|
|||
|
echo "String \"string1\" is null."
|
|||
|
fi # Not quoting "$string1" now gives wrong result!
|
|||
|
|
|||
|
exit 0 # Thank you, also, Florian Wisser, for the "heads-up".</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><DIV
|
|||
|
CLASS="EXAMPLE"
|
|||
|
><A
|
|||
|
NAME="EX14"
|
|||
|
></A
|
|||
|
><P
|
|||
|
><B
|
|||
|
>Example 7-7. <I
|
|||
|
CLASS="FIRSTTERM"
|
|||
|
>zmore</I
|
|||
|
></B
|
|||
|
></P
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>#!/bin/bash
|
|||
|
# zmore
|
|||
|
|
|||
|
# View gzipped files with 'more' filter.
|
|||
|
|
|||
|
E_NOARGS=85
|
|||
|
E_NOTFOUND=86
|
|||
|
E_NOTGZIP=87
|
|||
|
|
|||
|
if [ $# -eq 0 ] # same effect as: if [ -z "$1" ]
|
|||
|
# $1 can exist, but be empty: zmore "" arg2 arg3
|
|||
|
then
|
|||
|
echo "Usage: `basename $0` filename" >&2
|
|||
|
# Error message to stderr.
|
|||
|
exit $E_NOARGS
|
|||
|
# Returns 85 as exit status of script (error code).
|
|||
|
fi
|
|||
|
|
|||
|
filename=$1
|
|||
|
|
|||
|
if [ ! -f "$filename" ] # Quoting $filename allows for possible spaces.
|
|||
|
then
|
|||
|
echo "File $filename not found!" >&2 # Error message to stderr.
|
|||
|
exit $E_NOTFOUND
|
|||
|
fi
|
|||
|
|
|||
|
if [ ${filename##*.} != "gz" ]
|
|||
|
# Using bracket in variable substitution.
|
|||
|
then
|
|||
|
echo "File $1 is not a gzipped file!"
|
|||
|
exit $E_NOTGZIP
|
|||
|
fi
|
|||
|
|
|||
|
zcat $1 | more
|
|||
|
|
|||
|
# Uses the 'more' filter.
|
|||
|
# May substitute 'less' if desired.
|
|||
|
|
|||
|
exit $? # Script returns exit status of pipe.
|
|||
|
# Actually "exit $?" is unnecessary, as the script will, in any case,
|
|||
|
#+ return the exit status of the last command executed.</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
></P
|
|||
|
><DIV
|
|||
|
CLASS="VARIABLELIST"
|
|||
|
><P
|
|||
|
><B
|
|||
|
><A
|
|||
|
NAME="CCOMPARISON1"
|
|||
|
></A
|
|||
|
>compound comparison</B
|
|||
|
></P
|
|||
|
><DL
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="COMPOUNDAND"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-a</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>logical and</P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="REPLACEABLE"
|
|||
|
><I
|
|||
|
>exp1 -a exp2</I
|
|||
|
></TT
|
|||
|
> returns true if
|
|||
|
<EM
|
|||
|
>both</EM
|
|||
|
> exp1 and exp2 are true.</P
|
|||
|
></DD
|
|||
|
><DT
|
|||
|
><A
|
|||
|
NAME="COMPOUNDOR"
|
|||
|
></A
|
|||
|
><SPAN
|
|||
|
CLASS="TOKEN"
|
|||
|
>-o</SPAN
|
|||
|
></DT
|
|||
|
><DD
|
|||
|
><P
|
|||
|
>logical or </P
|
|||
|
><P
|
|||
|
><TT
|
|||
|
CLASS="REPLACEABLE"
|
|||
|
><I
|
|||
|
>exp1 -o exp2</I
|
|||
|
></TT
|
|||
|
> returns
|
|||
|
true if either exp1 <EM
|
|||
|
>or</EM
|
|||
|
> exp2 is
|
|||
|
true.</P
|
|||
|
></DD
|
|||
|
></DL
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
> These are similar to the Bash comparison operators
|
|||
|
<B
|
|||
|
CLASS="COMMAND"
|
|||
|
>&&</B
|
|||
|
> and <B
|
|||
|
CLASS="COMMAND"
|
|||
|
>||</B
|
|||
|
>, used
|
|||
|
within <A
|
|||
|
HREF="testconstructs.html#DBLBRACKETS"
|
|||
|
>double brackets</A
|
|||
|
>.
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>[[ condition1 && condition2 ]]</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</P
|
|||
|
><P
|
|||
|
> The <B
|
|||
|
CLASS="COMMAND"
|
|||
|
>-o</B
|
|||
|
> and <B
|
|||
|
CLASS="COMMAND"
|
|||
|
>-a</B
|
|||
|
> operators
|
|||
|
work with the <A
|
|||
|
HREF="testconstructs.html#TTESTREF"
|
|||
|
>test</A
|
|||
|
> command or
|
|||
|
occur within single test brackets.
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>if [ "$expr1" -a "$expr2" ]
|
|||
|
then
|
|||
|
echo "Both expr1 and expr2 are true."
|
|||
|
else
|
|||
|
echo "Either expr1 or expr2 is false."
|
|||
|
fi</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</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
|
|||
|
>But, as <EM
|
|||
|
>rihad</EM
|
|||
|
> points out:
|
|||
|
<TABLE
|
|||
|
BORDER="0"
|
|||
|
BGCOLOR="#E0E0E0"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
><FONT
|
|||
|
COLOR="#000000"
|
|||
|
><PRE
|
|||
|
CLASS="PROGRAMLISTING"
|
|||
|
>[ 1 -eq 1 ] && [ -n "`echo true 1>&2`" ] # true
|
|||
|
[ 1 -eq 2 ] && [ -n "`echo true 1>&2`" ] # (no output)
|
|||
|
# ^^^^^^^ False condition. So far, everything as expected.
|
|||
|
|
|||
|
# However ...
|
|||
|
[ 1 -eq 2 -a -n "`echo true 1>&2`" ] # true
|
|||
|
# ^^^^^^^ False condition. So, why "true" output?
|
|||
|
|
|||
|
# Is it because both condition clauses within brackets evaluate?
|
|||
|
[[ 1 -eq 2 && -n "`echo true 1>&2`" ]] # (no output)
|
|||
|
# No, that's not it.
|
|||
|
|
|||
|
# Apparently && and || "short-circuit" while -a and -o do not.</PRE
|
|||
|
></FONT
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
>
|
|||
|
</P
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
><P
|
|||
|
>Refer to <A
|
|||
|
HREF="ops.html#ANDOR"
|
|||
|
>Example 8-3</A
|
|||
|
>, <A
|
|||
|
HREF="arrays.html#TWODIM"
|
|||
|
>Example 27-17</A
|
|||
|
>,
|
|||
|
and <A
|
|||
|
HREF="contributed-scripts.html#WHX"
|
|||
|
>Example A-29</A
|
|||
|
> to see compound comparison operators
|
|||
|
in action.</P
|
|||
|
></DIV
|
|||
|
><H3
|
|||
|
CLASS="FOOTNOTES"
|
|||
|
>Notes</H3
|
|||
|
><TABLE
|
|||
|
BORDER="0"
|
|||
|
CLASS="FOOTNOTES"
|
|||
|
WIDTH="100%"
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
ALIGN="LEFT"
|
|||
|
VALIGN="TOP"
|
|||
|
WIDTH="5%"
|
|||
|
><A
|
|||
|
NAME="FTN.AEN3669"
|
|||
|
HREF="comparison-ops.html#AEN3669"
|
|||
|
><SPAN
|
|||
|
CLASS="footnote"
|
|||
|
>[1]</SPAN
|
|||
|
></A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
ALIGN="LEFT"
|
|||
|
VALIGN="TOP"
|
|||
|
WIDTH="95%"
|
|||
|
><P
|
|||
|
>As S.C. points out, in a compound test,
|
|||
|
even quoting the string variable might not
|
|||
|
suffice. <TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>[ -n "$string" -o "$a" = "$b" ]</B
|
|||
|
></TT
|
|||
|
>
|
|||
|
may cause an error with some versions of Bash if
|
|||
|
<TT
|
|||
|
CLASS="VARNAME"
|
|||
|
>$string</TT
|
|||
|
> is empty. The safe way
|
|||
|
is to append an extra character to possibly empty variables,
|
|||
|
<TT
|
|||
|
CLASS="USERINPUT"
|
|||
|
><B
|
|||
|
>[ "x$string" != x -o "x$a" = "x$b" ]</B
|
|||
|
></TT
|
|||
|
>
|
|||
|
(the <SPAN
|
|||
|
CLASS="QUOTE"
|
|||
|
>"x's"</SPAN
|
|||
|
> cancel out).</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="fto.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="nestedifthen.html"
|
|||
|
ACCESSKEY="N"
|
|||
|
>Next</A
|
|||
|
></TD
|
|||
|
></TR
|
|||
|
><TR
|
|||
|
><TD
|
|||
|
WIDTH="33%"
|
|||
|
ALIGN="left"
|
|||
|
VALIGN="top"
|
|||
|
>File test operators</TD
|
|||
|
><TD
|
|||
|
WIDTH="34%"
|
|||
|
ALIGN="center"
|
|||
|
VALIGN="top"
|
|||
|
><A
|
|||
|
HREF="tests.html"
|
|||
|
ACCESSKEY="U"
|
|||
|
>Up</A
|
|||
|
></TD
|
|||
|
><TD
|
|||
|
WIDTH="33%"
|
|||
|
ALIGN="right"
|
|||
|
VALIGN="top"
|
|||
|
>Nested <TT
|
|||
|
CLASS="REPLACEABLE"
|
|||
|
><I
|
|||
|
>if/then</I
|
|||
|
></TT
|
|||
|
> Condition Tests</TD
|
|||
|
></TR
|
|||
|
></TABLE
|
|||
|
></DIV
|
|||
|
></BODY
|
|||
|
></HTML
|
|||
|
>
|