IFS=$'\n' 的确切含义是啥?

Posted

技术标签:

【中文标题】IFS=$\'\\n\' 的确切含义是啥?【英文标题】:What is the exact meaning of IFS=$'\n'?IFS=$'\n' 的确切含义是什么? 【发布时间】:2011-05-06 21:46:46 【问题描述】:

如果以下示例将IFS 环境变量设置为换行符...

IFS=$'\n'
美元符号是什么意思 确实? 它在这个特定的 案例? 我可以在哪里阅读有关此特定用法的更多信息(Google 不允许在搜索中使用特殊字符,我不知道要查找什么其他内容)?

我知道IFS 环境变量是什么,\n 字符是什么(换行),但为什么不直接使用以下形式: IFS="\n"(哪个不行)?

例如,如果我想遍历文件的每一行并想使用 for 循环,我可以这样做:

for line in (< /path/to/file); do
    echo "Line: $line"
done

但是,除非将IFS 设置为换行符,否则这将无法正常工作。为了让它工作,我必须这样做:

OLDIFS=$IFS
IFS=$'\n'
for line in (< /path/to/file); do
    echo "Line: $line"
done
IFS=$OLDIFS

注意:我不需要其他方法来做同样的事情,我已经知道很多其他方法了...我只是对 $'\n' 感到好奇,想知道是否有人可以给我一个解释。

【问题讨论】:

【参考方案1】:

问题:

IFS=$'\n'的确切含义是什么?

简单回答:

嘿,巴什!将 Internal Field Separator (IFS) 设置为 New Line


IFS 是什么?

IFS 是字符,Bash 在处理字符串时用作单词/项目边界。

设置为空格制表符换行的空白字符,默认。 p>

示例 1:

使用IFS的默认值

string="first second:third forth:fifth"

for item in $string; do
    echo "$item"
done

输出:

first
second:third
forth:fifth

示例 2:

IFS 设置为:

# Set the IFS to collon (:) character
IFS=:

string="first second:third forth:fifth"

for item in $string; do
    echo "$item"
done

输出:

first second  
third forth  
fifth

【讨论】:

【参考方案2】:

通常bash 不会解释字符串文字中的转义序列。因此,如果您写 \n"\n"'\n',那不是换行符 - 它是字母 n(在第一种情况下)或反斜杠后跟字母 n(在其他两种情况下) .

$'somestring'带有转义序列的字符串文字的语法。所以不像'\n'$'\n'实际上是一个换行符。

【讨论】:

并非如此——\n 只是一个(转义的)字母 n。你说得对,'\n'"\n" 是反冲,后面跟着 n。 请注意,$'\n' 是特定于 bash 的——它不能在 POSIX shell (/bin/sh) 中工作。要以符合 POSIX 的方式获得相同的效果,您可以输入 IFS=',然后按回车键输入一个实际的换行符,然后输入结束 ' IFS=$(echo -e '\n') 也应该以兼容 POSIX 的方式进行。 @Vineet - 它让我停下来对一个赞成的评论提出异议。虽然这个 Posix 正确的,但它不起作用 - bash 中的命令替换运算符删除所有尾随换行符。见this for more detail。 @DigitalTrauma 我认为它甚至不是 POSIX:-e 没有定义,而没有 -e\n 可以作为 XSI 扩展:pubs.opengroup.org/onlinepubs/9699919799/utilities/…。 printf '\n' 岩石 ;)【参考方案3】:

ANSI C 引用的字符串是一个关键点。感谢@mklement0。

您可以使用命令 od 测试 ANSI C 引用的字符串。

echo -n $'\n' | od -c
echo -n '\n' | od -c
echo -n $"\n" | od -c
echo -n "\n" | od -c

输出:

0000000  \n  
0000001

0000000   \   n   
0000002

0000000   \   n   
0000002

0000000   \   n   
0000002

你可以通过输出清楚地知道含义。

【讨论】:

【参考方案4】:

只是为了给构造一个正式名称$'...' 形式的字符串被称为 ANSI C-quoted strings

也就是说,与 [ANSI] C 字符串一样,反斜杠转义序列被识别并扩展为它们的等效文字(有关支持的转义序列的完整列表,请参见下文)。

这个扩展之后,$'...' 字符串的行为与 '...' 字符串相同 - 即,它们被视为文字 不受任何 [进一步] shell 扩展的影响

例如,$'\n' 扩展为文字换行符 - 这是常规 bash 字符串文字(无论是 '...' 还是 "...")无法做到的。[1]

另一个有趣的特性是 ANSI C 引用的字符串可以将 '(单引号)转义为 \',而 '...'(常规的单引号字符串)不能: p>

echo $'Honey, I\'m home' # OK; this cannot be done with '...'

支持的转义序列列表

反斜杠转义序列,如果存在,解码如下:

\a 警报(铃声)

\b 退格

\e \E 转义字符(不是 ANSI C)

\f 换页

\n 换行

\r 回车

\t 水平制表符

\v 垂直制表符

\ 反斜杠

\' 单引号

\" 双引号

\nnn 八位字符,其值为八进制值 nnn(一到三位)

\xHH 八位字符,其值为十六进制值 HH(一个或两个十六进制数字)

\uHHHH Unicode (ISO/IEC 10646) 字符,其值为十六进制值 HHHH(一到四个十六进制数字)

\UHHHHHHHH Unicode (ISO/IEC 10646) 字符,其值为十六进制值 HHHHHHHH(1 到 8 个十六进制数字)

\cx 一个 control-x 字符

扩展的结果是单引号的,就好像美元符号不存在一样。


[1] 但是,您可以在 '...' 和 "..." 字符串中嵌入 actual 换行符;即,您可以定义跨越多行的字符串。

【讨论】:

【参考方案5】:

重新恢复默认 IFS - 这个OLDIFS=$IFS 不是必需的。在 subshel​​l 中运行新的 IFS 以避免覆盖默认的 IFS:

ar=(123 321); ( IFS=$'\n'; echo $ar[*] )

此外,我真的不相信您可以完全恢复旧的 IFS。你应该用双引号来避免换行,比如OLDIFS="$IFS"

【讨论】:

这是一个非常有用的技术。我只是将它用于更清洁的外壳连接操作:args=$(IFS='&amp;'; echo "$*")。以 Bourne shell 友好的方式将 IFS 恢复为 $' \t\n' 绝非易事。 回复Besides I don't really believe you recover the old IFS fully:分词在变量赋值的RHS上执行(但引号删除是),所以OLDIFS=$IFSOLDIFS="$IFS"的行为方式相同.【参考方案6】:

这就像从变量中检索值:

VAR='test'
echo VAR
echo $VAR

是不同的,所以美元符号基本上是评估内容的。

【讨论】:

这与变量无关。 $'FOO' (与 $FOO 不同,这不是问题所在)是字符串文字。如果你执行echo $'VAR',你会看到它打印的是字符串VAR,而不是test【参考方案7】:

来自http://www.linuxtopia.org/online_books/bash_guide_for_beginners/sect_03_03.html

“$'STRING'”形式的单词是 以特殊方式处理。这个单词 展开为字符串,其中 反斜杠转义字符被替换 由 ANSI-C 标准规定。 反斜杠转义序列可以是 在 Bash 文档中找到。发现

我猜这是强制脚本将换行符转义为正确的 ANSI-C 标准。

【讨论】:

以上是关于IFS=$'\n' 的确切含义是啥?的主要内容,如果未能解决你的问题,请参考以下文章

编程中“厨房水槽”的确切含义是啥?

JPA @Entity 注解的确切含义是啥?

依赖范围的确切含义是啥,例如构建、测试等

NHibernate中持久性模型的确切含义是啥?

git中“我们的”和“他们的”的确切含义是啥?

Angular 2\TypeScript 中 export 关键字的确切含义是啥?