代码之家  ›  专栏  ›  技术社区  ›  akaihola dnlcrl

如何在引号表达式中转义扩展路径名扩展模式?

  •  4
  • akaihola dnlcrl  · 技术社区  · 17 年前

    除了基本 * , ? [...] 模式,Bash shell提供了扩展的模式匹配运算符,如 !(pattern-list) (“匹配除一个给定模式外的所有模式”)。这个 extglob 需要设置shell选项才能使用它们。举个例子:

    ~$ mkdir test ; cd test ; touch file1 file2 file3
    ~/test$ echo *
    file1 file2 file3
    ~/test$ shopt -s extglob  # make sure extglob is set
    ~/test$ echo !(file2)
    file1 file3
    

    如果我将shell表达式传递给在子shell中执行它的程序,则运算符会导致错误。这是一个直接运行子shell的测试(这里我从另一个目录执行,以确保扩展不会过早发生):

    ~/test$ cd ..
    ~$ bash -c "cd test ; echo *"
    file1 file2 file3
    ~$ bash -c "cd test ; echo !(file2)"  # expected output: file1 file3
    bash: -c: line 0: syntax error near unexpected token `('
    bash: -c: line 0: `cd test ; echo !(file2)'
    

    我试过各种各样的逃跑方法,但我想出来的都没有奏效。我也怀疑 extglob 没有设置在子shell中,但事实并非如此:

    ~$ bash -c "shopt -s extglob ; cd test ; echo !(file2)"
    bash: -c: line 0: syntax error near unexpected token `('
    bash: -c: line 0: `cd test ; echo !(file2)'
    

    任何解决方案都值得赞赏!

    4 回复  |  直到 17 年前
        1
  •  3
  •   Randy Proctor    17 年前

    bash在执行每一行之前都会对其进行解析,因此当bash验证globbing模式语法时,“shopt-s extglob”不会生效。该选项不能在同一行上启用。这就是为什么“bash-O extglob-c'xyz'”解决方案(来自Randy Proctor)有效并且是必需的。

        2
  •  4
  •   Tony Delroy    15 年前
    $bash-O extglob-c'echo!(文件2)'
    文件1文件3
    
        3
  •  3
  •   Dennis Williamson    17 年前

    如果你想避免,还有另一种方法 eval 你需要能够转身 extglob 在潜艇壳内时断时续。只需将您的模式放入变量中:

    bash -c 'shopt -s extglob; cd test; patt="!(file2)"; echo $patt; shopt -u extglob; echo $patt'
    

    给出以下输出:

    file1 file3
    !(file2)
    

    证明这一点 extglob 已设置和未设置。如果第一个 echo 周围有报价 $patt ,它只会像第二个一样吐出图案 回声 (可能应该有引号)。

        4
  •  1
  •   Nietzche-jou    17 年前

    嗯,我没有任何实际经验 extglob ,但我可以通过包装来让它工作 echo 在A eval :

    $ bash -c 'shopt -s extglob ; cd  test ; eval "echo !(file2)"'
    file1 file3