`IFS=$'\n' 中的 '\n' 是一个变量吗?

Abs*_*cDo 13 bash

我注意到设置换行符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还补充道\u000aksh93并且bash也有\cj同时zsh拥有\C-Jksh93还支持像\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 listinvi是否$IFS包含该代码中的其他间距字符之类的东西之外,人们无法看到)。

IFS=:, IFS=':', IFS=":",IFS=$':'都将 IFS 设置为,:因此您使用哪个并不重要。

$'...'至少支持(有变化):ksh93, zsh, bash, mksh, busybox sh, FreeBSD shksh93并且bash还有一种$"..."用于文本本地化的引号形式,尽管它很少使用,因为部署和使用便携和可靠很麻烦。

esfish壳还可以使用\n引号以外拓展到新行。

一些工具,如printfecho或 的一些实现也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"字符结尾,而不是换行符。

现在,为了完整性,在rcshell 和派生类(如esakanga)中,$'\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 字节作为分隔符进行编码的)。


Ste*_*itt 11

这是ANSI-C 引用

表格$'string'中的词被特殊处理。单词扩展为string,并按照 ANSI C 标准的规定替换反斜杠转义字符。

因此$'\n'被换行符替换。

这是无关的外壳参数扩展,尽管使用了$


sch*_*ily 6

字符串 like$'\n'已经被引入ksh93并且目前不是 POSIX 标准的一部分。

它们允许使用大多数类似 C 的转义,例如$'\u2345',也支持的转义echo

请注意,如果您不喜欢(在 ksh93 或 bash 的情况下)使用该转义方法,您仍然可以使用:

IFS='
'
Run Code Online (Sandbox Code Playgroud)

这是等效的,但更难阅读。

BTW:这个扩展已经通过了 POSIX 标准委员会,但它计划在SUSv8中出现,预计不会在 2020 年之前出现,因为我们首先需要解决我们落后于当前错误列表的问题。