Skip to main content
added 2 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88+¹ or bash, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(xx|y) there!

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88+¹ or bash, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x) there!

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88+¹ or bash, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x|y) there!

added 8 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88 or bash, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x) there!

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88+¹, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x) there!

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88 or bash, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x) there!

added 236 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93's¹'s @(x&y&z) operator:

      case $string in
        ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
          echo is 12 characters long AND starts with a vowel AND ends in a decimal
      esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

      set -o extendedglob
      case $string in
        ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
          echo is 12 characters long AND starts with a vowel AND ends in a decimal
      esac
    
  • ksh88, bash, using double negation with OR (!(!(x)|!(y)|!(z)))

      shopt -s extglob # bash only
      case $string in
        ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
          echo is 12 characters long AND starts with a vowel AND ends in a decimal
      esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x) there!

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93's @(x&y&z) operator:

      case $string in
        ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
          echo is 12 characters long AND starts with a vowel AND ends in a decimal
      esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

      set -o extendedglob
      case $string in
        ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
          echo is 12 characters long AND starts with a vowel AND ends in a decimal
      esac
    
  • ksh88, bash, using double negation with OR (!(!(x)|!(y)|!(z)))

      shopt -s extglob # bash only
      case $string in
        ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
          echo is 12 characters long AND starts with a vowel AND ends in a decimal
      esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.

For completeness, while case has a | OR operator, it doesn't have an AND operator but if using shells with extended glob operators (ksh, zsh, bash), you can implement the AND in the pattern syntax:

  • ksh93¹'s @(x&y&z) operator:

    case $string in
      ( @({12}(?)&~(i:[aeiou]*)&*[0123456789]) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • zsh (using ~ (AND-NOT) combined with ^ (NOT)): x~^y~^z

    set -o extendedglob
    case $string in
      ( ?(#c12)~^(#i)[aeiou]*~^*[0-9] )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    
  • ksh88, using double negation with OR (!(!(x)|!(y)|!(z)))

    shopt -s extglob # bash only
    case $string in
      ( !(!(????????????)|!([aAeEıiIİoOuU]*)|!(*[0123456789])) )
        echo is 12 characters long AND starts with a vowel AND ends in a decimal
    esac
    

In any case, remember that except in zsh where ranges are always based on codepoint values, ranges like [0-9] cannot be used reliably outside of the POSIX/C locale (hence the [0123456789] instead above).

ksh93 and zsh's case insensitive matching operators (~(i) and (#i)) honour the locale for case sensitive comparison. For instance, in a Turkish locale on a GNU system, (#i)[aeiou] will match on İ, but not I (because uppercase i is İ there). To get a consistent outcome regardless of the locale, you may want to hard code all possible values instead like in the ksh88/bash approach.


¹ Beware that ksh88 and older versions of ksh93 had that misfeature by which if a string didn't match a pattern, case would fall back to do a literal match. For instance, the @(x|y) pattern matches on both x and y but also on @(x) there!

deleted 1 character in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k
Loading
added 1 character in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k
Loading
added 18 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k
Loading
added 18 characters in body
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k
Loading
Source Link
Stéphane Chazelas
  • 584.5k
  • 96
  • 1.1k
  • 1.7k
Loading