bash 脚本中扩展 glob 模式的行为不一致

bash 脚本中扩展 glob 模式的行为不一致

以下 Bash (v 5.1.4) 脚本

#!/usr/bin/env bash
echo $BASHOPTS
shopt extglob
x="123"
if [[ "$x" == +([[:digit:]]) ]]; then 
    echo "[[ Ok!" 
fi
case $x in
    +([[:digit:]])) echo "case Ok" ;;
    *) echo case "KO" ;;
esac

输出

checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
extglob         off
[[ Ok!
./extglob_test.sh: line 10: syntax error near unexpected token `('
./extglob_test.sh: line 10: `    +([[:digit:]])) echo "case Ok" ;;'

这向我提出了几个问题:

  1. shopt extglob说它已关闭,因此第 9 行的 case 选项在逻辑上失败。但为什么第 5 行代码会成功呢?

  2. env 变量 BASHOPTS 包含继承的 shopt 选项,BASH 手册指出:

    BASHOPTS
      A  colon-separated  list of enabled shell options.  Each word in the list is a valid argument for the -s option to the shopt
      builtin command (see SHELL BUILTIN COMMANDS below).  The options appearing in BASHOPTS are those reported as  on  by  shopt.
      If this variable is in the environment when bash starts up, each shell option in the list will be enabled before reading any
      startup files.  This variable is read-only.
    

    所以我希望extglob在脚本中看到启用。事实上,echo $BASHOPTS在 shell 提示符处发出命令会输出:

    checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:progcomp:promptvars:sourcepath
    

    但是,我们可以看到存在一些差异,特别是此处存在的选项extglob,但在脚本的输出中缺失。

    当然,如果我启用脚本第 3 行中extglob的选项,我会得到:shopt -s extglob

    checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
    [[ Ok!
    case Ok
    
  3. 然而,linter(我在 Vim 中使用 Ale)仍然在第 9 行发出语法错误信号

有任何想法吗?

答案1

有3个问题。

  1. 正如评论所说,[[默认情况下启用内部 extglob。

  2. 您没有环境变量 BASHOPTS。您可以通过跑步export | grep BASHOPTS但看不到任何东西来看到这一点。正如你引用的那样“如果这个变量在 bash 启动时的环境中...”您需要export BASHOPTS在交互式 shell 中运行。

  3. 获得更好的短绒棉绒!

相关内容