Reputation: 759
I usually use pattern matching in [[ command, but I wanted to use it in case command.
#!/bin/bash
bash -version|head -1
# Test 1:
[[ apple79 == apple@(14|38|79|11) ]] && echo ok 1
# Test2:
case apple79 in apple@(14|38|79|11)) echo ok 2;; *) ;; esac
When I run the above test.sh
at terminal with .
command everything is normal.
. test.sh
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
ok 1
ok 2
But when I try to run it so:
./t.sh
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
ok 1
./t.sh: line 6: syntax error near unexpected token `('
./t.sh: line 6: ` case apple79 in apple@(14|38|79|11)) echo ok 2;; *) ;; esac'
I have received an error messages for the case command. I have seen some bash pattern matching doc eg.: https://www.linuxjournal.com/content/pattern-matching-bash But I have no any idea for this problem.
Upvotes: 1
Views: 298
Reputation: 1428
The difference is between interactive and non-interactive shell options. By default extglob are turned off for non-interactive shells, so you can do:
bash -i t.sh
or add
shopt -s extglob
at the beginning of your script
Upvotes: 2
Reputation: 85895
The error is most likely because you have turned on extglob
option in your current shell. Because sourcing the script takes the current shell's options and extended options, it works when sourcing the script.
But when doing the ./t.sh
you are launching an explicit shell which does not have the option turned on by default. Since [[
operator with ==
turns on extglob
by default, it works for the first test but fails for the case
statement. To enable the option explicitly in scripts do shopt -s extglob
at the top of your script.
As you can see below the pattern works with case
only if the option is enabled. Try removing -O extglob
from below command and you can see it doesn't work.
bash -O extglob -c 'case apple79 in apple@(14|38|79|11)) echo ok 2;; *) ;; esac'
As far why your attempt didn't work, try adding a line shopt extglob
to your t.sh
and repeat your tests. You'll notice that when the script is sourced you'll see extglob on
and for the executed case get extglob off
Upvotes: 2
Reputation: 532418
The extglob
option is implicitly enabled inside [[ ... ]]
for pattern matching, but you need to enable it explicitly to use it with the case
statement.
#!/bin/bash
shopt -s extglob
[[ apple79 == apple@(14|38|79|11) ]] && echo ok 1
case apple79 in apple@(14|38|79|11)) echo ok 2;; *) ;; esac
Upvotes: 3