如何在bash中扩展“word”?不讨论文件通配符

如何在bash中扩展“word”?不讨论文件通配符

抱歉这么简单的问题,但我自己找不到解决方案。

我跑:

$ echo {1..4}
1 2 3 4

这对我来说没问题。但如果我:

$ echo "{1..4}" > file

$ cat file
{1..4}

$ echo $(<file)
{1..4}

$ echo $(cat file)
{1..4}

我正在寻找一种使用来扩展{1..4}文件内的字符串的方法,但没有成功。fileecho

答案1

您只是没有使用正确的工具来完成这项工作:

[user@host dir]$ ksh
$ echo "{1..4}" > file
$ cat file
{1..4}
$ echo $(<file)
1 2 3 4
$ echo $(cat file)
1 2 3 4

抛开笑话不谈,Bash 中的扩展顺序是:

  1. 支撑扩张;
  2. 波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);
  3. 分词;
  4. 和文件名扩展。

因此,在 中echo $(cat file),(不带引号的)命令替换的输出仅进行分词和文件名扩展,保持不变,因为它不包含模式匹配字符(并假设您的IFS变量不包含{1.4}

虽然某些扩展可以嵌套,结果对于会触发从阶段到当前阶段的扩展的字符,通常不会再次解析扩展的字符。 (有充分的理由:想想foo=\$foo; echo "$foo")。

要将大括号扩展应用于file您需要构建一个新的命令行并让 shell 解析并执行它的内容。一种方法是eval,如图所示这个另一个答案你有。或者,您可以使用进程替换:

$ . <(printf '%s ' echo; cat file)
1 2 3 4

请注意,在这两种情况下,的全部内容file将被解析并执行在目前的环境下。

类似地,但在新进程的单独环境中执行bash

$ bash <<<$( printf "%s " echo; cat file; )
1 2 3 4

顺便说一句,ksh93(我在第一个代码块中使用的 shell)以一种特殊的方式运行:大括号扩展在稍后阶段执行,作为字段拆分的一部分,并且重新解析先前扩展的结果以检测大括号表达式1

$ bash -c 'echo {1..$(printf %s 3)}' mybash
{1..3}
$ ksh -c 'echo {1..$(printf %s 3)}' myksh
1 2 3

1 饰演 史蒂芬·查泽拉斯评论中指出,ksh93 的这种行为可以被视为一个 bug,并且不符合 POSIX,因为它使得有可能$var不扩展到 的值var

答案2

我想你正在寻找这个:

eval "echo $(cat file)"

eval 构造一个命令,然后由 shell 执行该命令。

相关内容