为什么“echo $(cat /path/to/fileName)”列出我的文件和方向?

为什么“echo $(cat /path/to/fileName)”列出我的文件和方向?

当我使用 打印出文件内容时echo $(cat /path/to/filename),它也会列出我的文件和说明。但是当我使用 时,printf "$(cat /path/to/filename)\n"它工作正常。

我也尝试将其保存到变量中content='cat /path/to/filename'(也content=$(cat /path/to/filename),然后通过打印echo $content,但得到了相同的结果(列出文件和方向)。

我想将文件的内容存储到变量中,并将变量传递到我的脚本中作为下一个命令的输入。

请注意,我的文件内容*中包含特殊字符。

答案1

因为执行命令替换后,如果不引用它们,shell 会对结果执行单词拆分(或字段拆分)。

POSIX 定义单词扩展作为:

字扩展的顺序如下:

  1. 应从头到尾执行波浪符号扩展(参见波浪符号扩展)、参数扩展(参见参数扩展)、命令替换(参见命令替换)和算术扩展(参见算术扩展)。请参阅标记识别中的第 5 条。

  2. 应针对步骤 1 生成的字段部分执行字段拆分(参见字段拆分),除非 IFS 为空

  3. 除非 set -f 有效,否则应执行路径名扩展(参见路径名扩展)。

  4. 删除引号(参见删除引号)应始终最后执行。

在您的例子中,*匹配当前工作目录中的所有内容。您必须引用结果才能获得预期的输出:

echo "$(cat /path/to/fileName)"

答案2

引用:

$ echo "*" >> test
$ echo $(cat test)
bash43-001 bash43-002 bash43-003 bash43-004 bash43-005 test
$ echo "$(cat test)"
*

第一条规则是,始终引用命令替换。

除非您关闭通配符(或)或引用/转义它: ,否则裸字符*将在 中展开。对于命令输出,最好始终使用引号。bashset -fsetopt noglob"*" \*

相关内容