什么是“ IFS”?


Answers:


17

IFS代表-它是分隔字段的字符。在您发布的示例中,将其设置为换行符();因此设置后,将逐行处理文本。在该示例中,您可以将(更改为输入文件中的某个字母)的值,并检查如何拆分文本。Input Internal Field Separator\nforIFS

顺便说一句,从您发布的答案的第二个解决方案是建议...

正如@jasonwryan注意到的,不是,Input而是Internal。名称Input来自awk其中还有OFS- Output Field Separator


1
请注意,IFS还用于组合输出参数。在bash手册页中:“当扩展用双引号引起时,它将扩展为单个单词,每个参数的值由IFS特殊变量的第一个字符分隔。”
埃里克

还应该注意的是,它S是用于Bourne外壳中的分隔符的,而它是它的起源。在Korn外壳以及现在已由指定的大多数其他Bourne-like外壳中,Delimiter POSIXSis(只是有点想像力)A::B:例如被分为“ A”,“”和“ B”(没有多余的内容) “”)。不同于awkFS或的s参数扩展标志zsh
斯特凡Chazelas

27

IFS与循环不直接相关,与单词拆分有关。IFS间接确定命令的输出如何分解成循环迭代的部分。

当您进行无保护的变量替换$foo或命令替换时$(foo),有两种情况:

  • 如果上下文期望一个单词,例如当替换是在双引号之间"$foo"或在变量赋值中x=$foo,则替换产生的字符串将按原样使用。
  • 如果上下文期望多个单词(大多数情况下是这种情况),则对结果字符串执行两个进一步的扩展:
    • 字符串分成单词。出现的任何字符都$IFS被视为单词分隔符。例如IFS=":"; foo="12:34::78"; echo $foo打印12 34 ​ 78(带之间有两个空格3478,因为有一个空字)。
    • 每个单词都被视为全局模式,并扩展为文件名列表。例如,foo="*"; echo $foo打印当前目录中的文件列表。

像许多其他上下文一样,对于循环,需要单词列表。所以

for x in $(foo); do 

分解$(foo)为单词,并将每个单词视为全局模式。的默认值IFS空格,制表符和换行,因此,如果foo打印出两条线hello worldhowdy然后循环体与执行x=hello,然后x=worldx=howdy。如果IFS显式更改为仅包含换行符,则对hello world和执行循环howdy。如果IFS被改变为o正,则循环用于执行hell​ wrld​␤h(其中,​␤是一个新行字符)和wdy


为什么在中提到“间接” "IFS indirectly determines how ..."
αғsнιη

1
@αғsнιη IFS(直接)确定如何分解命令替换的输出,然后(间接)确定循环循环的内容。
吉尔斯(Gilles)'所以

5

man bash

IFS内部字段分隔符,用于在扩展后进行单词拆分,并使用read Builtin命令将行拆分为单词。默认值为“ <space> <tab> <newline>”。

这是Bash的内部变量之一。它确定Bash在解释字符串时如何识别字段或单词边界。

虽然它默认为空格(空格,制表符和换行符),但是可以更改它,例如解析逗号分隔的数据文件。

http://tldp.org/LDP/abs/html/internalvariables.html


0

除了以前的出色答案之外,我还想补充一点,IFS对于在简单情况下与set结合使用对于高效且可移植的解析非常有用。高效,因为避免使用子外壳和生成工具(例如grep或sed):

resolutions="640x480,320x240"
xIFS=$IFS
IFS=','
for res in $resolutions; do
    xxIFS=$IFS
    IFS='x'
    set -- $res
    width=$1
    height=$2
    # handle width and height
    IFS=$xxIFS
done;
IFS=$xIFS

请注意,我们需要存储和恢复IFS的先前值,以避免脚本其他部分发生意外损坏。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.