Differences between revisions 10 and 14 (spanning 4 versions)
Revision 10 as of 2009-02-14 04:30:51
Size: 1586
Editor: GreyCat
Comment: add extglob solution
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 12: Line 12:
[[glob|Extended globs]] can also do this within a `[[` command: In Bash and ksh, [[glob|Extended globs]] can also do this within a `[[` command:
Line 14: Line 14:
   # bash/ksh -- ksh does not need the shopt
   shopt -s extglob
   if [[ $var = @(foo|bar|more) ]]; then
   # bash/ksh
   ${BASH_VERSION+shopt -s extglob}
   if [[ $var == @(foo|bar|more) ]]; then
Line 21: Line 21:
And here's one that uses `=~` (which requires bash 3.0 or higher): Alternatively, you may loop over a list of patterns, checking each individually.
Line 23: Line 23:
   regex='^(foo|bar|more)$'
   if [[ $var =~ $regex ]]; then
      ...
   fi
    # 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
Line 29: Line 40:
This one '''only works in bash 3.1''' and '''some 3.2 revisions''' (it is untested in 3.0): For logical conjunction (return true if `$var` matches all patterns), ksh93 can use the `&` pattern delimiter.
Line 31: Line 43:
   if [[ $var =~ '^(foo|bar|more)$' ]]; then
     
...
   fi
    # ksh93 only
   
[[ $var == @(foo&bar&more) ]] && ...
Line 36: Line 47:
The `=~` operator behavior changes drastically between 3.1 and 3.2, so be careful with it. The above expression is tested to work in bash ''3.1'' and ''3.2.{13,15,17}''; and it doesn't work in ''3.2.0''.
Please also note that the regexp does not need to be quoted in the 3.2 revisions where it works. --[[redondos]]
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.
Line 39: Line 49:
Normally I would never advocate [[BashFAQ/050|sticking code into a variable]] and attempting to use it -- lots of people have ''enormous'' trouble because they try to do that. In the case of `=~`, though, it seems to be required. Personally, I'd just stick with the `case`. --GreyCat {{{
    # bash/ksh88/etc...
    ${BASH_VERSION+shopt -s extglob}
    [[ $var == !(!(foo)|!(bar)|!(more)) ]] && ...
}}}
Line 41: Line 55:
The regexp works as long as it is quoted with bash version ''3.00.15(1)-release'' on CentOS4/RHEL4. I didn't bother checking whether bash is a patched version or not in CentOS4/RHEL4. --ellingsw 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)