tags:

views:

487

answers:

5

I'm not familiar with the semantics of the "-@" in the bash script snippet below, which is from /etc/bash_completion.d/subversion. I'm trying to understand why bash reports "syntax error near unexpected token '(' on this line, I have two questions:

  1. What is "-@()" expected to do here?
  2. Why might bash be unhappy with this statement?

    case $prev in
                    # other cases omitted
     -@(F|-file|-targets))
      _filedir
      return 0;
      ;;
                    # other cases omitted
            esac
    
+3  A: 

The '@(...)' here is part of Bash's pattern matching syntax. It's an "or", it simply matches one of the listed patterns, separated by pipe characters.

The initial dash has simply been factored out of the expression; "-@(a|b|c)" is the same as "@(-a|-b|-c)", but shorter.

As pointed out by a commenter (thanks!) this requires Bash's extglob enabled to work. This is done like so:

shopt -s extglob

You can check if you already have it enabled like this:

shopt extglob
unwind
I'm guessing "-@(F|-file|-targets)" is equivalent to "-F|--file|--targets" (where '|' means "or"), but I haven't been able to confirm from documentation.
Lance Richardson
http://www.gnu.org/software/bash/manual/bashref.html#Pattern-Matching See the bottom of the section where `extglob` is mentioned.
ephemient
A: 

The "@" is a pattern that means "match one and only one". And you seem to have an extra closing paren in your code example, which is either a typo or your syntax error.

Andrew Barnett
Isn't the closing paren part of the case syntax? See here, for instance: <http://www.gnu.org/software/bash/manual/bashref.html#index-case-53>.
unwind
A: 

This is completely a guess, as I'm not familiar with all of the bash syntax, but I think it should be more like:

@(-F|-file|-targets))

...which makes sense given the other answers here - @() matches one of the command arguments, and the extra ) is part of the case structure. I just think the dash is in the wrong place.

DGM
See Lance Richardson's comment on unwind's answer.
Dennis Williamson
+1  A: 

I've found the answer to the second part of my question, which is that in order for the "@(...)" to be enabled, the "extglob" shell option needs to be on. Executing:

shopt -s extglob

before executing the script eliminates the error.

Lance Richardson