使用 printf 命令时需要转义哪些字符?

Har*_*her 9 shell posix printf

我想澄清一下,我不是在谈论如何在解释的 shell 级别上转义字符。

据我所知,只需要转义两个字符:%\

要打印文字%,您必须使用前面的 将其转义%

printf '%%'
Run Code Online (Sandbox Code Playgroud)

要打印文字,\您必须使用前面的 将其转义\

printf '\\'
Run Code Online (Sandbox Code Playgroud)

是否有任何其他情况我需要转义字符才能按字面意思解释?

Sté*_*las 6

在 的格式参数中printf,只有%\字符是特殊的(不,"不是特殊的并且\"每个 POSIX都未指定)。

但是,两个重要的注意事项。

  1. 在大多数printfimplementations¹,它的字节值\%类的特殊和POSIX规范甚至可以被解释为需要它,因为它需要的printf实用程序是在一个接口printf(3)的C函数,而不是wprintf(3)例如(如它需要%.3s截断到3个字节而不是 3 个字符)。

    在某些字符编码,包括BIG5和GB18030,有数百个字符包含反斜杠的编码,并逃避那些printf,你需要插入\每个前0x5c这些字符的编码内字节!

    例如在 BIG5-HKSCS 中,例如在zh_HK.big5hkscs(香港)语言环境中使用的,所有都???????????????????????????????????????????????????????????????????????????????????????????????????????????????包含字节 0x5c(这也是 的编码\)。

    对于大多数printf实现,在该语言环境中,printf '?b'不输出?b但字节0xa3( 编码的第一个字节?)后跟 BS 字符( 的扩展\b)。

    $ LC_ALL=zh_HK.big5hkscs luit
    $ locale charmap
    BIG5-HKSCS
    $ printf '?b' | LC_ALL=C od -tx1 -tc
    0000000  a3  08
            243  \b
    0000002
    
    Run Code Online (Sandbox Code Playgroud)

    最好避免使用(甚至安装/提供)这些语言环境,因为它们会导致各种此类错误和漏洞。

  2. 一些printf实现支持选项,甚至那些不需要支持--作为选项分隔符的实现。因此printf --不会输出--但可能会报告有关缺少格式参数的错误。因此,如果您不能保证您的格式不会以 开头-,则必须使用--选项分隔符:

     printf -- "$escaped_format" x y...
    
    Run Code Online (Sandbox Code Playgroud)

无论如何,如果你想打印任意字符串,你可以使用:

printf '%s\n' "$data" # with terminating newline
printf %s "$data"     # without
Run Code Online (Sandbox Code Playgroud)

传递给的字符串中没有特殊字符%s(但请注意,除了printf内置的 之外zsh,您不能在任何printf参数中传递 NUL 字符)。

请注意,虽然在基于 ASCII 的系统上输入文字的规范方式\是 with\\和文字%with %%,但您也可以使用\134and\45和一些printf实现\x5c, \x25, or \x{5c}, \x{25}, or (甚至在非 ASCII 系统上): \u005c, \u0025or \u{5c}, \u{25}.


¹yashprintf内置是我所知道的唯一例外。