抱歉这么简单的问题,但我自己找不到解决方案。
我跑:
$ 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}
文件内的字符串的方法,但没有成功。file
echo
答案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 中的扩展顺序是:
- 支撑扩张;
- 波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);
- 分词;
- 和文件名扩展。
因此,在 中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 执行该命令。