Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is @(...|...|...) syntax in bash?

To focus on the @() syntax mentionned in this question :

[[ $OSTYPE == *@(darwin|freebsd|solaris|cygwin|openbsd)* ]]

Where does this syntax come from ? Why is it used in this case ? And what is the difference with :

[[ $OSTYPE =~ (darwin|freebsd|solaris|cygwin|openbsd) ]]

or

[[ $OSTYPE == *(darwin|freebsd|solaris|cygwin|openbsd) ]]

that all seems equivalents.

Is this syntax used in place of the =~ operator for better portability with regex ?

Thanks for your clarifications

like image 943
SLePort Avatar asked Mar 05 '16 09:03

SLePort


2 Answers

Search for the extglob option in man bash:

If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a |. Composite patterns may be formed using one or more of the following sub-patterns:

?(pattern-list)
    Matches zero or one occurrence of the given patterns
*(pattern-list)
    Matches zero or more occurrences of the given patterns
+(pattern-list)
    Matches one or more occurrences of the given patterns
@(pattern-list)
    Matches one of the given patterns
!(pattern-list)
    Matches anything except one of the given patterns
like image 99
choroba Avatar answered Oct 22 '22 16:10

choroba


This uses rules explained in the Pattern Matching section of man bash:

[[ $OSTYPE == *@(darwin|freebsd|solaris|cygwin|openbsd)* ]]

This uses regular expressions to perform the matching:

[[ $OSTYPE =~ (darwin|freebsd|solaris|cygwin|openbsd) ]]

These are very different mechanisms, with different performance implications. There are no patterns in the values darwin, freebsd, ..., these are simple literal strings. The @(...) syntax is perfect for such simpler matching logic, so using regular expressions seems overkill.

In this example both writing styles give the same behavior, it's just that they perform the matching through different mechanisms. If instead of a list of literal strings like darwin, freebsd, ... you had more complex regex patterns, then the first writing style wouldn't be an option, you would need to use the second version with full regex power.

Is this syntax used in place of the =~ operator for better portability with regex ?

It is used because it is good enough for the purpose, regex not needed.

like image 30
janos Avatar answered Oct 22 '22 15:10

janos