bash printf转义/引用功能背后的基本原理是什么?

bash printf转义/引用功能背后的基本原理是什么?,bash,Bash,使用bash 4.4,如果我想在脚本中打印参数,并转义所有可能的非文字字符,那么我可以使用: printf '%q\n' "${@}" printf '%s\n' "${@@Q}" 如果我想引用这些论点,那么我可以使用: printf '%q\n' "${@}" printf '%s\n' "${@@Q}" 例如: $ cat tst.sh #!/usr/bin/env bash printf 'Escaped: %q\n' "${@}" echo '---' printf 'Quot

使用bash 4.4,如果我想在脚本中打印参数,并转义所有可能的非文字字符,那么我可以使用:

printf '%q\n' "${@}"
printf '%s\n' "${@@Q}"
如果我想引用这些论点,那么我可以使用:

printf '%q\n' "${@}"
printf '%s\n' "${@@Q}"
例如:

$ cat tst.sh
#!/usr/bin/env bash

printf 'Escaped: %q\n' "${@}"
echo '---'
printf 'Quoted: %s\n' "${@@Q}"

$ ./tst.sh 'foo bar' 'other .* args'
Escaped: foo\ bar
Escaped: other\ .\*\ args
---
Quoted: 'foo bar'
Quoted: 'other .* args'
为什么??为什么我们不干脆用一些格式说明符,比如
%E
表示
转义的
%Q
表示
%Q
的格式说明符,而不是
转义的
格式说明符,然后用一种完全不同的、神秘的语法表示
“${*@Q}”
当与
%s
结合使用时,表示
引用的


使用字母
q
而不是
E
,例如,生成转义是令人费解的,但我认为这背后有一些历史原因,但我更感兴趣的是为什么他们不能在第二种情况下使用简单的
%Q
或类似的printf修饰符来提高我对shell如何工作的理解,因为现在我不明白为什么当前语法是必需的。

在编写使用这些功能的脚本时,可以信任的唯一保证是文档中给出的保证,如下所示:

对于打印文件“%q”

%q
-引用参数的方式可以重新用作shell输入

对于
@Q
参数转换:

扩展是一个字符串,它是以可重用为输入的格式引用的参数值


值得注意的是,不保证其中任何一方会使用单引号、反斜杠或任何其他特定形式;唯一的保证是两者都将生成可重用为输入的输出

其他一切都是未记录的实现细节,因此易于更改


此外,一些证据表明,这两种结构的行为在实践中可能与问题中给出的描述不同:

$ nl=$'\n'
$ printf '%q\n' "$nl"  # in bash 5.0, emits $'\n', not a backslash followed by a newline
$ printf '%s\n' "${nl@Q}" # in bash 5.0, emits $'\n', not a newline in single-quotes

…这进一步证明了这两种构造都可以生成不能移植到基线POSIX shell的代码,因此“重用为shell输入”或“重用为输入”规范指的是bash本身的评估。

注意,
@Q
相当于
printf“%Q\n'${}”
将是
printf'%s\n'${@Q}“
,而不是
printf'%s\n'${*@Q}”
。不过,不确定这是否会对你的问题产生影响。请注意,
@Q
并不是作为引用修饰符添加的新语法;这是同时添加的许多新扩展时间运营商之一……因为没有人费心添加一个?这是一个历史问题,而不是技术问题。
%q
无法可靠地转义单个字符。它没有被指定以这种方式运行,也不能保证在每个实例中都这样做。在f/e中,您会注意到它使用带有
$'…'
-样式引号的文字换行符来引用字符串。我不会特别建议在没有明确文档的情况下,将观察到的行为概括为意图……也就是说,
printf%q
绝对不能保证在下一版本中,
${…@q}
使用引号的地方会继续使用反斜杠。
printf%q
@q
都只保证它们的输出可以作为输入重复使用(由同一个shell使用,而不保证与其他POSIX超集shell甚至之前的版本兼容);除此之外的一切都是实现的意外。谢谢,很高兴我问了,所以我现在知道不要使用它们中的任何一个从脚本生成可视化格式的输出,因为它们生成的格式将来可能会更改!就我个人而言,当我想要更可靠的东西时,我实际上会调用Python解释器;Python2的
pipes.quote()
或Python3的
shlex.quote()
也没有关于精确输出的正式规范,但至少保证生成可由POSIX shell解析的输出。