Differences between revisions 1 and 14 (spanning 13 versions)
Revision 1 as of 2007-05-03 00:00:48
Size: 191
Editor: redondos
Comment:
Revision 14 as of 2013-01-14 22:03:43
Size: 1555
Editor: ormaaj
Comment: Stupid mksh. Why the does shift throw fatal errors when POSIX doesn't require it to?!? Add "command" workaround (POSIX doesn't require that either, but it works everywhere except mksh).
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq66)]]
== I want to check if [[ $var == foo || $var == bar || $var = more ]] without repeating $var n times. ==
<<Anchor(faq66)>>
== I want to check if [[ $var == foo || $var == bar || $var == more ]] without repeating $var n times. ==
The portable solution uses `case`:
Line 5: Line 6:
   case $var in    # Bourne
case "$var" in
Line 9: Line 11:

In Bash and ksh, [[glob|Extended globs]] can also do this within a `[[` command:
{{{
   # bash/ksh
   ${BASH_VERSION+shopt -s extglob}
   if [[ $var == @(foo|bar|more) ]]; then
      ...
   fi
}}}

Alternatively, you may loop over a list of patterns, checking each individually.
{{{
    # bash/ksh93/zsh (w/ emulate ksh)

    # usage: pmatch string pattern [ pattern ... ]
    function pmatch {
        ${1+typeset x=}"${1-false}" &&
        while command shift; do
            [[ $x == $1 ]] && return
        done 2>/dev/null
        return 1
    }

    var='foo bar'
    if pmatch "$var" foo bar baz foo\* blarg; then
        : ...
    fi
}}}

For logical conjunction (return true if `$var` matches all patterns), ksh93 can use the `&` pattern delimiter.

{{{
    # ksh93 only
    [[ $var == @(foo&bar&more) ]] && ...
}}}

For shells that support only the ksh88 subset (extglob patterns), you may [[http://en.wikipedia.org/wiki/DeMorgan%27s_Law | DeMorganify]] the logic using the negation sub-pattern operator.

{{{
    # bash/ksh88/etc...
    ${BASH_VERSION+shopt -s extglob}
    [[ $var == !(!(foo)|!(bar)|!(more)) ]] && ...
}}}

But this is quite unclear and not much shorter than just writing out separate expressions for each pattern.
----
CategoryShell

I want to check if [[ $var == foo || $var == bar || $var == more ]] without repeating $var n times.

The portable solution uses case:

   # Bourne
   case "$var" in
      foo|bar|more) ... ;;
   esac

In Bash and ksh, Extended globs can also do this within a [[ command:

   # bash/ksh
   ${BASH_VERSION+shopt -s extglob}
   if [[ $var == @(foo|bar|more) ]]; then
      ...
   fi

Alternatively, you may loop over a list of patterns, checking each individually.

    # bash/ksh93/zsh (w/ emulate ksh)

    # usage: pmatch string pattern [ pattern ... ]
    function pmatch {
        ${1+typeset x=}"${1-false}" &&
        while command shift; do
            [[ $x == $1 ]] && return
        done 2>/dev/null
        return 1
    }

    var='foo bar'
    if pmatch "$var" foo bar baz foo\* blarg; then
        : ...
    fi

For logical conjunction (return true if $var matches all patterns), ksh93 can use the & pattern delimiter.

    # ksh93 only
    [[ $var == @(foo&bar&more) ]] && ...

For shells that support only the ksh88 subset (extglob patterns), you may DeMorganify the logic using the negation sub-pattern operator.

    # bash/ksh88/etc...
    ${BASH_VERSION+shopt -s extglob}
    [[ $var == !(!(foo)|!(bar)|!(more)) ]] && ...

But this is quite unclear and not much shorter than just writing out separate expressions for each pattern.


CategoryShell

BashFAQ/066 (last edited 2022-11-23 19:29:49 by GreyCat)