I'm trying to use a pretty basic Bash parameter expansion in a script and it's not working; it works fine when I run it in my interactive shell, though. Here's the little test script:
<~> $ cat /tmp/foo
#!/usr/bin/env bash
foo="bar 1.2.3"
echo $foo
echo ${foo##*([^0-9])}
echo ${foo/a/-}
The first param expansion (${foo##*([^0-9])}
) doesn't work when I run the script, but the second one (${foo/a/-}
) does:
<~> $ /tmp/foo
bar 1.2.3
bar 1.2.3
b-r 1.2.3
If I source it instead (running it in my current shell), it works as expected:
<~> $ . /tmp/foo
bar 1.2.3
1.2.3
b-r 1.2.3
Suspecting a difference in actual shell being run, shell version, or settings, I expanded the script:
<~> $ cat /tmp/foo
#!/usr/bin/env bash
echo "SHELL: $SHELL"
echo "VERSION: $BASH_VERSION"
echo
set -o
echo
foo="bar 1.2.3"
echo $foo
echo ${foo##*([^0-9])}
echo ${foo/a/-}
And now I get this:
<~> $ /tmp/foo
SHELL: /opt/local/bin/bash
VERSION: 5.1.16(1)-release
allexport off
braceexpand on
emacs off
errexit off
errtrace off
functrace off
hashall on
histexpand off
history off
ignoreeof off
interactive-comments on
keyword off
monitor off
noclobber off
noexec off
noglob off
nolog off
notify off
nounset off
onecmd off
physical off
pipefail off
posix off
privileged off
verbose off
vi off
xtrace off
bar 1.2.3
bar 1.2.3
b-r 1.2.3
Nothing looks out of place, and running the two and comparing the output shows nothing of significance:
<~> $ diff <(/tmp/foo) <(. /tmp/foo)
6c6
< emacs off
---
> emacs on
11,12c11,12
< histexpand off
< history off
---
> histexpand on
> history on
16c16
< monitor off
---
> monitor on
33c33
< bar 1.2.3
---
> 1.2.3
Any ideas on what I'm missing here (besides a clue, 'natch)? Thanks!
Just to paint a complete picture derived from the accepted answer below, adding in shopt
to the script output shows these additional differences between the script version and the interactive shell's version:
52c52
< expand_aliases off
---
> expand_aliases on
54c54
< extglob off
---
> extglob on
61c61
< histappend off
---
> histappend on
64c64
< hostcomplete on
---
> hostcomplete off
72c72
< login_shell off
---
> login_shell on
and indeed there is the missing option (extglob
).
You need to add
shopt -s extglob
to the script to enable *(pattern-list)
extended globbing. I suspect you have this enabled in interactive shells in your .bashrc
.