我注意到设置换行符IFS
应该以 $ 作为前缀
IFS=$'\n'
Run Code Online (Sandbox Code Playgroud)
但如果设置一个冒号,就
IFS=:
Run Code Online (Sandbox Code Playgroud)
是\n
变量吗?
Sté*_*las 21
那$'...'
inbash
不是参数扩展,它是一种特殊的引用,由 引入ksh93
,将那些\n
, \x0a
,\12
代码扩展为换行符。zsh
还补充道\u000a
。ksh93
并且bash
也有\cj
同时zsh
拥有\C-J
。ksh93
还支持像\x{a}
.
这$
是一个暗示它是某种形式或扩展。但在任何情况下,它与使用$
(如$((1 + 1))
,$param
或$(cmd)
)的其他形式的扩展不同,因为它不在双引号或此处的文档中执行(尽管所有 shell 中的echo "$'x'"
输出$'x'
均未根据 POSIX 指定)并且其扩展不受拆分+glob,它绝对比扩展运算符更接近引用运算符。
IFS=\n
将 IFS 设置为n
(\
被视为引用运算符) 和IFS="\n"
或IFS='\n'
将 IFS 设置为两个字符反斜杠和n
。
您还可以使用:
IFS='
'
Run Code Online (Sandbox Code Playgroud)
或者
IFS="
"
Run Code Online (Sandbox Code Playgroud)
或者
IFS=$'
'
Run Code Online (Sandbox Code Playgroud)
传递一个文字换行符,尽管这不太清晰(除了使用诸如set list
invi
是否$IFS
包含该代码中的其他间距字符之类的东西之外,人们无法看到)。
IFS=:
, IFS=':'
, IFS=":"
,IFS=$':'
都将 IFS 设置为,:
因此您使用哪个并不重要。
$'...'
至少支持(有变化):ksh93
, zsh
, bash
, mksh
, busybox sh
, FreeBSD sh
。ksh93
并且bash
还有一种$"..."
用于文本本地化的引号形式,尽管它很少使用,因为部署和使用便携和可靠很麻烦。
在es
与fish
壳还可以使用\n
引号以外拓展到新行。
一些工具,如printf
、echo
或 的一些实现也awk
可以\n
自行扩展。例如,可以这样做:
printf '\n'
awk 'BEGIN{printf "\n"}'
echo
echo '\n\c' # UNIX compliant echos only
Run Code Online (Sandbox Code Playgroud)
到换行符的输出,但请注意:
IFS=$(printf '\n')
将不起作用,因为命令替换 ( $(...)
) 会删除所有尾随换行符。但是,您可以使用:
eval "$(printf 'IFS="\n"')"
Run Code Online (Sandbox Code Playgroud)
之所以有效,是因为输出printf
以"
字符结尾,而不是换行符。
现在,为了完整性,在rc
shell 和派生类(如es
或akanga
)中,$'\n'
确实是该\n
变量的扩展(名称是两个字符\
和的序列的变量n
)。这些 shell 对变量名称可以包含的字符没有限制,并且只有一种类型的引号:'...'
.
$ rc
; '\n' = (foo bar)
; echo $'\n'
foo bar
; echo $'\n'(1)
foo
Run Code Online (Sandbox Code Playgroud)
rc
变量也全部导出到环境中,但至少在 的 Unix 变体中rc
,对于像 一样的变量名称\n
,环境变量版本经历了一种编码形式:
; env | grep foo | sed -n l
__5cn=foo\001bar$
Run Code Online (Sandbox Code Playgroud)
(0x5c
作为 ASCII 的字节值\
;另请参阅该数组变量是如何使用 0x1 字节作为分隔符进行编码的)。
字符串 like$'\n'
已经被引入ksh93
并且目前不是 POSIX 标准的一部分。
它们允许使用大多数类似 C 的转义,例如$'\u2345'
,也支持的转义echo
。
请注意,如果您不喜欢(在 ksh93 或 bash 的情况下)使用该转义方法,您仍然可以使用:
IFS='
'
Run Code Online (Sandbox Code Playgroud)
这是等效的,但更难阅读。
BTW:这个扩展已经通过了 POSIX 标准委员会,但它计划在SUSv8中出现,预计不会在 2020 年之前出现,因为我们首先需要解决我们落后于当前错误列表的问题。