代码之家  ›  专栏  ›  技术社区  ›  Ed Morton

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

  •  0
  • Ed Morton  · 技术社区  · 5 年前

    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 对于 Escaped %Q 对于 Quoted %q 意思是 逃脱 "${*@Q}" %s 方法 ?

    q 而不是 E ,比如说,产生逃逸是令人困惑的,但我想这背后有一些历史原因,但我更感兴趣的是技术原因背后为什么他们不能使用一个简单的 %问 或者第二种情况下类似的printf修饰符来提高我对shell一般工作方式的理解,因为现在我不明白为什么需要当前语法。

    1 回复  |  直到 5 年前
        1
  •  4
  •   Charles Duffy    5 年前

    在编写使用这些工具的脚本时,可以信任的唯一保证是文档中提供的保证,如下所示:

    为了 printf '%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外壳的代码,因此“重用为外壳输入”或“重用为输入”规范引用bash本身的计算。