Linux的IFS
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux的IFS相关的知识,希望对你有一定的参考价值。
参考技术A Linux下有一个特殊的环境变量叫做IFS,叫做内部字段分隔符(internal field separator)。IFS环境变量定义了bash shell用户字段分隔符的一系列字符。默认情况下,bash shell会将下面的字符当做字段分隔符:空格、制表符、换行符。Bash shell会将上面的三个字符当做列表中新字段的开始。例如, 1 2 3 字符串在shell中会当做三个字段1,2,3。如果想要以逗号分隔字段,则要修改IFS的值,修改如下:
参考资料:
IFS=$'\n' 的确切含义是啥?
【中文标题】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】:来自http://www.linuxtopia.org/online_books/bash_guide_for_beginners/sect_03_03.html:
“$'STRING'”形式的单词是 以特殊方式处理。这个单词 展开为字符串,其中 反斜杠转义字符被替换 由 ANSI-C 标准规定。 反斜杠转义序列可以是 在 Bash 文档中找到。发现
我猜这是强制脚本将换行符转义为正确的 ANSI-C 标准。
【讨论】:
【参考方案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】:
这就像从变量中检索值:
VAR='test'
echo VAR
echo $VAR
是不同的,所以美元符号基本上是评估内容的。
【讨论】:
这与变量无关。$'FOO'
(与 $FOO
不同,这不是问题所在)是字符串文字。如果你执行echo $'VAR'
,你会看到它打印的是字符串VAR
,而不是test
。【参考方案4】:
重新恢复默认 IFS - 这个OLDIFS=$IFS
不是必需的。在 subshell 中运行新的 IFS 以避免覆盖默认的 IFS:
ar=(123 321); ( IFS=$'\n'; echo $ar[*] )
此外,我真的不相信您可以完全恢复旧的 IFS。你应该用双引号来避免换行,比如OLDIFS="$IFS"
。
【讨论】:
这是一个非常有用的技术。我只是将它用于更清洁的外壳连接操作:args=$(IFS='&'; echo "$*")
。以 Bourne shell 友好的方式将 IFS
恢复为 $' \t\n'
绝非易事。
回复Besides I don't really believe you recover the old IFS fully
:分词不在变量赋值的RHS上执行(但引号删除是),所以OLDIFS=$IFS
和OLDIFS="$IFS"
的行为方式相同.【参考方案5】:
只是为了给构造一个正式名称:$'...'
形式的字符串被称为 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 换行符;即,您可以定义跨越多行的字符串。
【讨论】:
【参考方案6】: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
你可以通过输出清楚地知道含义。
【讨论】:
【参考方案7】:问题:
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
【讨论】:
以上是关于Linux的IFS的主要内容,如果未能解决你的问题,请参考以下文章