Bash 参数扩展“${var##pat}”在脚本中的行为不同于 shell
Bash param expansion "${var##pat}" behaves differently in script than in shell
我正在尝试在脚本中使用非常基本的 Bash 参数扩展,但它不起作用;不过,当我在我的交互式 shell 中 运行 它时它工作正常。这是小测试脚本:
<~> $ cat /tmp/foo
#!/usr/bin/env bash
foo="bar 1.2.3"
echo $foo
echo ${foo##*([^0-9])}
echo ${foo/a/-}
当我 运行 脚本时,第一个参数扩展 (${foo##*([^0-9])}
) 不起作用,但第二个 (${foo/a/-}
) 可以:
<~> $ /tmp/foo
bar 1.2.3
bar 1.2.3
b-r 1.2.3
如果我改用它(运行在我当前的 shell 中使用它),它会按预期工作:
<~> $ . /tmp/foo
bar 1.2.3
1.2.3
b-r 1.2.3
怀疑实际 shell 与 运行、shell 版本或设置存在差异,我扩展了脚本:
<~> $ 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/-}
现在我明白了:
<~> $ /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
看起来没有什么不妥,运行对两者进行比较并比较输出没有任何意义:
<~> $ 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
关于我在这里遗漏的任何想法(除了线索,'natch)?谢谢!
附录
只是为了从下面接受的答案中得出完整的图片,在脚本输出中添加 shopt
显示了脚本版本和交互式 shell 版本之间的这些额外差异:
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
确实缺少选项 (extglob
)。
您需要添加
shopt -s extglob
添加到脚本以启用 *(pattern-list)
扩展通配。我怀疑您在 .bashrc
.
的交互式 shell 中启用了此功能
我正在尝试在脚本中使用非常基本的 Bash 参数扩展,但它不起作用;不过,当我在我的交互式 shell 中 运行 它时它工作正常。这是小测试脚本:
<~> $ cat /tmp/foo
#!/usr/bin/env bash
foo="bar 1.2.3"
echo $foo
echo ${foo##*([^0-9])}
echo ${foo/a/-}
当我 运行 脚本时,第一个参数扩展 (${foo##*([^0-9])}
) 不起作用,但第二个 (${foo/a/-}
) 可以:
<~> $ /tmp/foo
bar 1.2.3
bar 1.2.3
b-r 1.2.3
如果我改用它(运行在我当前的 shell 中使用它),它会按预期工作:
<~> $ . /tmp/foo
bar 1.2.3
1.2.3
b-r 1.2.3
怀疑实际 shell 与 运行、shell 版本或设置存在差异,我扩展了脚本:
<~> $ 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/-}
现在我明白了:
<~> $ /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
看起来没有什么不妥,运行对两者进行比较并比较输出没有任何意义:
<~> $ 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
关于我在这里遗漏的任何想法(除了线索,'natch)?谢谢!
附录
只是为了从下面接受的答案中得出完整的图片,在脚本输出中添加 shopt
显示了脚本版本和交互式 shell 版本之间的这些额外差异:
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
确实缺少选项 (extglob
)。
您需要添加
shopt -s extglob
添加到脚本以启用 *(pattern-list)
扩展通配。我怀疑您在 .bashrc
.