代码之家  ›  专栏  ›  技术社区  ›  weakish

无法理解Fish shell中的命令替换

  •  5
  • weakish  · 技术社区  · 14 年前

    在sh中:

    ~$ `echo ls`
    bin/  Desktop/
    

    fish: Illegal command name “(echo ls)”
    ~% (echo ls)
    

    (请注意,错误消息显示在命令行上方。)

    ~% echo (echo ls)
    ls
    ~% eval (echo ls)
    bin/  Desktop/
    
    fish: Illegal command name “(echo ls)”
    exec (echo ls)
         ^
    ~% exec (echo ls)
    

    似乎命令替换只是作为命令的参数,而不是作为命令本身?为什么?

    好吧,医生说

    如果参数包含一组括号,则括号内的文本将被解释为命令列表。

    2 回复  |  直到 9 年前
        1
  •  7
  •   weakish    4 年前

    fish的最新版本(我在3.1.2上测试过)更新并 set cmd ls; $cmd

    怎么

    这是因为命令替换属于参数扩展,不允许作为命令。

    在sh中:

    tmpls=ls
    $tmpls
    

    % set cmd ls; $cmd
    fish: Variables may not be used as commands.
    ...
    

    为什么?

    简言之,这有利于可验证性

    这个 article 详细说明:

        if true; then if [ $RANDOM -lt 1024 ]; then END=fi; else END=true; fi; $END
    

      FI=fi; foo() { if true; then true; $FI; }
    

    Fish避免了这种问题,因为变量不允许作为命令。任何可以用变量作为命令的操作都可以用eval命令或函数以更简洁的方式完成。

    出于同样的原因,命令替换不允许作为命令。

        2
  •  0
  •   Dennis Williamson    14 年前

    这与扩张的顺序有关。

    help expand-command-substitution 在里面 fish :

    当组合多个参数展开时,执行展开 按以下顺序:

     * Command substitutions
     * Variable expansions
     * Bracket expansion
     * Pid expansion
     * Wildcard expansion
    

    展开是从右到左执行的,嵌套的括号展开 由内而外进行。

    man bash :

    展开的顺序是:大括号展开、颚化符展开、参数展开、变量展开和算术展开以及命令替换(完成) 以从左到右的方式)、分词和路径名扩展。