通常,fish 参数在被注入到 fish 命令之前会被转义:
mqudsi@freebsd> echo hello > hello\ world.txt
mqudsi@freebsd> file (echo hello world.txt)
hello world.txt: ASCII text
但是,大括号扩展的结果没有正确转义,_并且_没有简单的方法可以手动转义它,因为在参数周围引入引号会破坏扩展:
mqudsi@freebsd> echo -n hello\ {1,2,3}.txt\n
hello 1.txt
hello 2.txt
hello 3.txt
如您所见,在第一个参数之后, echo
被传递了两个单独的参数hello
和#.txt
,导致单词前面有额外的空格。
将参数用引号括起来会导致以下结果:
mqudsi@freebsd> echo -n "hello\ {1,2,3}.txt\n"
hello\ {1,2,3}.txt\n
在尝试通过将转义引号插入原始字符串来解决此问题时(假设字符串的内容在替换之后和注入之前没有被转义)会导致引号被正确转义,从而阻止了所需的结果:
mqudsi@freebsd> echo -n \"hello\ {1,2,3}.txt\n\" "hello 1.txt " "hello 2.txt " "hello 3.txt
"
看起来参数扩展是在参数拆分阶段之后发生的。
echo
被传递了两个单独的参数 hello 和 #.txt,导致单词前面有额外的空格。
我不同意这个诊断。 echo
被传递了 3 个参数(每个参数以\n
结尾), echo
忠实地打印出来,中间有一个空格。 我在这里看不到错误。
这是我为调试参数所做的工作:
~> printf '«%s»' hei\ {1,2,3}.txt\n
«hei 1.txt
»«hei 2.txt
»«hei 3.txt
»⏎
这是我为调试参数所做的工作:
我使用string escape
,即
> string escape -- hello\ {1,2,3}.txt\n
hello\ 1.txt\n
hello\ 2.txt\n
hello\ 3.txt\n
这意味着你实际上得到了我所期望的。 你用“1”得到完整的论点,然后是“2”,然后是“3”。 完整的参数恰好包含一个换行符。
@mqudsi :我认为让你
(command)
)。 这意味着这里的\n
被换行符替换后没有特殊含义。 就其余部分而言,它是“一个角色”。 我们不需要_escape_角色,我们只是不运行拆分。或者在file (echo hello world.txt)
,“hello world.txt”_is not_ 转义为hello\ world.txt
,它只是没有拆分,因为没有换行符。 如果您有一个名为hello\nworld.txt
,这将产生与 bash 的空格问题类似的问题。
echo
在其参数之间插入空格(如果没有给出“-s”)。 这就是导致奇怪缩进的原因 - 因为空格发生在换行符之后。这意味着如果你想要输出
hello 1.txt
hello 2.txt
hello 3.txt
使用echo -s
或printf '%s\n' hello\ {1,2,3}.txt
。
我相信这是一个误解,而不是一个错误。 我对么?
对不起,各位! 我试图为一个问题提出一个最小的重现,但被完全不同的东西弄糊涂了。 我弄错了参数扩展的行为,特别是,我将它与限制为 1 的parallel
或xargs
的行为混淆,即我假设echo {1,2,3}
将扩展为 3每个带有 1 个参数的命令,而不是带有 3 个参数的 1 个命令。
谢谢你让我直截了当。