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

发布于 2024-09-10 03:58:36 字数 491 浏览 9 评论 0原文

在sh中:

~$ `echo ls`
bin/  Desktop/

但是在fish中:(

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)

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

嗯,帮助文档确实说

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

但还是,为什么?

In sh:

~$ `echo ls`
bin/  Desktop/

But in fish:

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

(Note that the error message appears above the command line.)

~% echo (echo ls)
ls
~% eval (echo ls)
bin/  Desktop/

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

It seems that command substitution only works as parameters of a command, not as a command itself? Why?

Well, the help doc does say

If a parameter contains a set of parenthesis, the text enclosed by the parenthesis will be interpreted as a list of commands.

But still, why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

感受沵的脚步 2024-09-17 03:58:36

更新

这个答案是十年前的2010年写的。
Fish 的最新版本(我在 3.1.2 上进行了测试)已更新并设置 cmd ls; $cmd 现在有效。

这是

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

类似的例子:

在sh中:

tmpls=ls
$tmpls

但在fish中:

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

为什么

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

文章 解释了详细信息:

由于在常规 shell 中允许使用变量作为命令,因此不可能可靠地检查脚本的语法。例如,这段 bash/zsh 代码可能合法,也可能不合法,具体取决于您的运气。你觉得自己很幸运吗?

 如果为真;那么如果 [ $RANDOM -lt 1024 ];那么 END=fi;否则结束=真;菲; $END

当用户按回车键时,bash 和 zsh 都会尝试确定当前缓冲区中的命令是否完成,但由于这样的问题,它们有时会失败。更糟糕的是,这段完全合法的代码被 bash 拒绝了:

<前><代码> FI=fi; foo() { 如果为真;则为真; $FI; }

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

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

(注意:引用的例子是不公平的,因为“if”和“fi”不是简单的命令而是保留字。请参阅下面的评论。)

Update

This answer was written ten year ago in 2010.
Recent versions of fish (I tested on 3.1.2) updated and set cmd ls; $cmd is valid now.

How

This because command substitutions belong to parameter expansions and are not allowed as commands.

A similar example:

in sh:

tmpls=ls
$tmpls

But in fish:

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

Why

In short, it's good for verifiability

This article explains details:

Since it is allowed to use variables as commands in regular shells, it is impossible to reliably check the syntax of a script. For example, this snippet of bash/zsh code may or may not be legal, depending on your luck. Do you feel lucky?

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

Both bash and zsh try to determine if the command in the current buffer is finished when the user presses the return key, but because of issues like this, they will sometimes fail. Even worse, this piece of perfectly legal code is rejected by bash:

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

Fish avoids this kind of problem, since variables are not allowed as commands. Anything you can do with variables as commands can be done in a much cleaner way using either the eval command or by using functions.

For the same reason, command substitutions are not allowed as commands.

(Note: The cited example is not fair, since 'if' and 'fi' are not simple commands but reserved words. See comments below.)

逆光下的微笑 2024-09-17 03:58:36

它与扩展的顺序有关。

来自 fish 中的 help Expand-command-substitution

组合多个参数扩展时,进行扩展
按以下顺序:

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

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

来自 man bash

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

It has to do with the order of expansions.

From help expand-command-substitution in fish:

When combining multiple parameter expansions, expansions are performed
in the following order:

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

Expansions are performed from right to left, nested bracket expansions
are performed from the inside and out.

From man bash:

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done
in a left-to-right fashion), word splitting, and pathname expansion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文