问题
在亚壳中设置'extglob‘选项时,Bash脚本的执行将失败,出现以下错误消息
/tmp/foo.sh: line 7: syntax error near unexpected token `('#!/usr/bin/env bash
set -euo pipefail
(
shopt -s extglob
for f in ?(.)!(|+(.)|vendor); do
echo "$f"
done
)它在函数内部以相同的方式失败。
#!/usr/bin/env bash
set -euo pipefail
list_no_vendor () {
shopt -s extglob
for f in ?(.)!(|+(.)|vendor); do
echo "$f"
done
}
list_no_vendor调查
在这两种情况下,在全局设置选项、子外壳或函数的以外的时,脚本都会成功执行。
令人惊讶的是,在本地设置时,在子subshell和函数中都有效地启用了“extglob”选项:
#!/usr/bin/env bash
set -euo pipefail
(
shopt -s extglob
echo 'In the subshell:' "$(shopt extglob)"
)
list_no_vendor () {
shopt -s extglob
echo 'In the function:' "$(shopt extglob)"
}
echo 'In the main shell:' "$(shopt extglob)"
list_no_vendor输出:
In the subshell: extglob on
In the main shell: extglob off
In the function: extglob on这使我对语法错误感到非常困惑。
解决办法
将heredoc传递给bash命令是可行的。
#!/usr/bin/env bash
set -euo pipefail
bash <<'EOF'
shopt -s extglob
echo 'In the child:' "$(shopt extglob)"
EOF
echo 'In the parent:' "$(shopt extglob)"输出:
In the child: extglob on
In the parent: extglob off不过,我很想在这里了解问题的要点。
发布于 2018-03-14 17:17:56
extglob是解析器使用的标志。函数、复合命令和C.在执行之前被完整地解析。因此,必须在解析该内容之前设置extglob;在执行时设置它,但在解析时间之后对以前解析的内容没有任何影响。
这也是为什么不能将shopt -s extglob; ls !(*.txt)作为一行运行(当extglob以前未设置时),但必须在这两个命令之间有一个换行符。
不是作为可接受的实践的一个例子,而是作为一个演示这种行为的例子,请考虑以下几点:
#!/usr/bin/env bash
(
shopt -s extglob
# Parse of eval'd code is deferred, so this succeeds
eval '
for f in ?(.)!(|+(.)|vendor); do
echo "$f"
done
'
)这里不会发生这样的错误,因为对传递给eval的内容的解析只在执行shopt -s extglob之后才发生,而不是在解析要在子subshell中运行的代码块时发生。
https://stackoverflow.com/questions/49283740
复制相似问题