问题描述
我注意到要在外壳中打印$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"
可以正确显示?
解决方法
$ echo $IFS
-一些显示特殊字符的参数?
echo
没有这样的参数
$ printf "$IFS" or $ printf '$IFS'
-为什么这些方法都不起作用?
- 第一个方法像
echo
一样对字符串进行插值,并像原样打印IFS
字符串-默认情况下是一堆空白。 - 第二个不进行插值,显然会打印
$IFS
。
printf "%q" $IFS
该变量已被扩展为空格,这些空格已被shell占用,因此没有任何内容作为第二个参数传递给printf
,因此%q
没有任何输入。
printf "%q" '$IFS'
字符串$IFS
作为参数传递给%q
,后者只是向其中添加转义字符。
您遇到了三个基本问题:
-
未加引号的变量引用(如
echo $IFS
和printf "%q" $IFS
中一样)会进行单词拆分。基本上,变量值中的任何空格都被视为“单词”(这些单词作为参数传递给命令)之间的分隔符。但是“空白”被定义为$IFS
中的字符(这就是它的作用!)。因此,整个变量的值将被视为只是间距,而不是实际内容,并且实际上消失了!这是为什么要在变量引用周围加上双引号的众多示例之一。
-
单引号字符串(如
printf '$IFS'
和printf "%q" '$IFS'
中)完全不进行变量扩展。在这种情况下,$IFS
只是文字字符串,而不是变量引用。 -
最后,
$IFS
中的默认字符在屏幕上并不是特别明显。printf "$IFS"
实际上确实正确打印了它们(除非出于某种原因在%
中放入了“\
”或“IFS
”),但是您看不到它们。默认情况下,$IFS
中的第一个字符是空格,因此在打印时,光标将移动到第二列,但看不到任何可见内容。第二个字符是一个制表符,因此光标会移到更远的位置,但实际上仍然看不到任何内容。然后,最后一个字符是换行符,因此光标将移至下一行的开头...同样,没有任何可见的显示。这就是为什么需要
printf %q
的原因-%q
格式将$IFS
中不完全可见的字符转换为可见的可读表示。
如果不引用该变量,则在扩展变量后进行单词拆分。单词拆分将IFS
中的所有字符视为单词定界符;单词之间连续的多个单词被折叠到一个空格中,如果输出完全是定界符,则什么都不会输出。
您需要在变量周围使用引号将其按字面输出。
然后,您需要使用%q
格式运算符将其输出为转义序列,以便查看各个字符是什么。否则,您将无法分辨出第二个字符是TAB,您只会在屏幕上看到一堆空格。换行符将转到下一行。