【问题标题】:Printing the IFS chars打印 IFS 字符
【发布时间】:2020-09-04 07:11:10
【问题描述】:

我注意到要在 shell 中打印 $IFS 变量的值,我必须执行以下操作:

$ printf '%s\nYour IFS is: %q' 'Hello' "$IFS"
Hello
Your IFS is: $' \t\n'

我的问题是为什么我需要以这种特殊方式传递IFS?例如,为什么(或为什么不)可以这样做:

  • $ echo $IFS -- 一些打印特殊字符的参数?
  • $ printf "$IFS"$ printf '$IFS' -- 为什么这些都不起作用?
  • 为什么$ printf "%q" $IFS$ printf "%q" '$IFS' 不能正确显示,而$ printf "%q" "$IFS" 可以?

【问题讨论】:

  • 这取决于您将 IFS 设置为什么。与任何可打印的字符串一样,您可以通过echo "$IFS" 显示它(当然,您需要引用它)。尝试(在子shell 中)IFS=Z; echo "$IFS"; exit,您将看到一个x 显示。但是,如果您有一个包含不可打印字符的变量,您将不会得到很多有趣的输出。这对于 IFS 和其他任何东西都是一样的。

标签: bash shell ifs


【解决方案1】:
  • $ echo $IFS -- 一些打印特殊字符的参数?

echo没有这样的参数

  • $ printf "$IFS" or $ printf '$IFS' -- 为什么这些都不行?
  1. 第一个像 echo 一样对字符串进行插值,并按原样打印 IFS 字符串 - 默认情况下是一堆空格。
  2. 第二个不做插值,明显打印$IFS
  • printf "%q" $IFS

该变量已被扩展为被 shell 吃掉的空格,因此没有任何内容作为第二个参数传递给 printf,因此 %q 没有可使用的输入。

  • printf "%q" '$IFS'

字符串$IFS 作为参数传递给%q,它只是添加了转义字符。

【讨论】:

    【解决方案2】:

    您遇到了三个基本问题:

    • 未加引号的变量引用(如echo $IFSprintf "%q" $IFS)会进行分词。基本上,变量值中的任何空格都被视为“单词”之间的分隔符(作为参数传递给命令)。但是“空白”被定义为$IFS 中的字符(这就是它的用途!)。因此,整个变量的值被视为只是间距,而不是实际内容,并且实际上消失了!

      这是为什么应该在变量引用周围加上双引号的众多示例之一。

    • 单引号字符串(如printf '$IFS'printf "%q" '$IFS')根本不进行变量扩展。在这些情况下,$IFS 只是一个文字字符串,而不是变量引用。

    • 最后,$IFS 中的默认字符在屏幕上并不是特别明显。 printf "$IFS" 实际上确实可以正确打印它们(除非您出于某种原因将“%”或“\”放入IFS),但您看不到它们。默认情况下,$IFS 中的第一个字符是空格,因此当打印该字符时,光标会移动到第二列,但不会出现任何可见的内容。第二个字符是制表符,因此光标移动得更远,但实际上什么也看不见。然后最后一个字符是换行符,所以光标移动到下一行的开头......再次,没有可见的东西出现。

      这就是需要printf %q 的原因——%q 格式将$IFS 中不真正可见的字符转换为可见、可读的表示。

    【讨论】:

      【解决方案3】:

      如果不引用变量,则在扩展变量后进行分词。分词将IFS中的所有字符视为分词;单词之间连续的多个被折叠成一个空格,如果输出完全是分隔符,则什么都不输出。

      您需要在变量周围使用引号来按字面意思输出它。

      然后您需要使用%q 格式运算符将其输出为转义序列,以便您查看各个字符是什么。否则您将无法判断第二个字符是 TAB,您只会在屏幕上看到一堆空格。换行符只会转到下一行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        • 1970-01-01
        • 2018-06-22
        • 2016-12-25
        • 1970-01-01
        相关资源
        最近更新 更多