首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当在子subshell或函数中设置“extglob”选项时,Bash脚本会引发语法错误

当在子subshell或函数中设置“extglob”选项时,Bash脚本会引发语法错误
EN

Stack Overflow用户
提问于 2018-03-14 17:05:27
回答 1查看 2.5K关注 0票数 15

问题

亚壳中设置'extglob‘选项时,Bash脚本的执行将失败,出现以下错误消息

代码语言:javascript
复制
/tmp/foo.sh: line 7: syntax error near unexpected token `('
代码语言:javascript
复制
#!/usr/bin/env bash
set -euo pipefail
(
    shopt -s extglob
    for f in ?(.)!(|+(.)|vendor); do
        echo "$f"
    done
)

它在函数内部以相同的方式失败。

代码语言:javascript
复制
#!/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”选项:

代码语言:javascript
复制
#!/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

输出:

代码语言:javascript
复制
In the subshell: extglob            on
In the main shell: extglob          off
In the function: extglob            on

这使我对语法错误感到非常困惑。

解决办法

将heredoc传递给bash命令是可行的。

代码语言:javascript
复制
#!/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)"

输出:

代码语言:javascript
复制
In the child: extglob           on
In the parent: extglob          off

不过,我很想在这里了解问题的要点。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-14 17:17:56

extglob是解析器使用的标志。函数、复合命令和C.在执行之前被完整地解析。因此,必须在解析该内容之前设置extglob;在执行时设置它,但在解析时间之后对以前解析的内容没有任何影响。

这也是为什么不能将shopt -s extglob; ls !(*.txt)作为一行运行(当extglob以前未设置时),但必须在这两个命令之间有一个换行符。

不是作为可接受的实践的一个例子,而是作为一个演示这种行为的例子,请考虑以下几点:

代码语言:javascript
复制
#!/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中运行的代码块时发生。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49283740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档