如何在命令替换期间禁用分词?

Pay*_*ian 3 zsh command-substitution

如何在命令替换期间禁用分词?这是问题的一个简化示例:

 下午 4:00 /用户/paymahn/下载
 ???猫测试.txt
你好\n世界
 下午 4:00 /用户/paymahn/下载
 ???echo $(cat test.txt)
你好
世界
 下午 4:00 /用户/paymahn/下载
 ???echo "$(cat test.txt)"
你好
世界
 下午 4:01 /用户/paymahn/下载
 ???echo "$(cat "test.txt" )"
你好
世界

我想要的是echo $(cat test.txt)(或包含命令替换的某些变体)输出hello\nworld.

我发现https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html在底部说,If the substitution appears within double quotes, word splitting and filename expansion are not performed on the results.但我似乎无法理解。我会认为我已经尝试过的示例之一符合该规则,但我想不是。

ilk*_*chu 10

将文字\n更改为换行符与分词无关,而是echo处理反斜杠。有些版本echo会这样做,有些则不会……echo默认情况下,Bash不处理反斜杠转义符(没有-e标志或xpg_echo选项),但是例如 dash 和 Zsh 版本的echodo。

$ cat test.txt 
hello\nworld
$ bash -c 'echo "$(cat test.txt)"'
hello\nworld
$ zsh -c 'echo "$(cat test.txt)"'
hello
world
Run Code Online (Sandbox Code Playgroud)

使用printf来代替:

$ bash -c 'printf "%s\n" "$(cat test.txt)"'
hello\nworld
$ zsh -c 'printf "%s\n" "$(cat test.txt)"'
hello\nworld
Run Code Online (Sandbox Code Playgroud)

另请参阅:为什么 printf 比 echo 好?

无论如何,您应该在命令替换周围加上引号,以防止在类似 sh 的 shell 中分词和通配符。(zsh 仅在命令替换时(不是在参数或算术扩展时)进行分词(而不是 globbing),sh 模式除外。)