gpt4 book ai didi

当在子 shell 或函数中设置 'extglob' 选项时,Bash 脚本会抛出语法错误

转载 作者:行者123 更新时间:2023-11-29 09:22:41 26 4
gpt4 key购买 nike

问题

当在 subshell 中设置 '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
)

它在 function 中以同样的方式失败:

#!/usr/bin/env bash
set -euo pipefail

list_no_vendor () {
shopt -s extglob
for f in ?(.)!(|+(.)|vendor); do
echo "$f"
done
}

list_no_vendor

调查

在这两种情况下,如果在子 shell 或函数的外部全局设置选项,脚本就会成功执行。

令人惊讶的是,当在本地设置时,“extglob”选项似乎在子 shell 和函数中都有效地启用了:

#!/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

但是我很想知道这里问题的要点。

最佳答案

extglob解析器 使用的标志。函数、复合命令等。在执行之前被完整地解析。因此,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 执行后发生,而不是在分析要在子 shell 中运行的代码块时。

关于当在子 shell 或函数中设置 'extglob' 选项时,Bash 脚本会抛出语法错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49283740/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com