bash 脚本中 IFS=$'\n' 的含义是什么?

bash 脚本中 IFS=$'\n' 的含义是什么?

bash shell 脚本的开头是以下行:

IFS=$'\n'

这组符号背后的含义是什么?

答案1

IFS代表“内部字段分隔符”。 shell 使用它来确定如何进行分词,即如何识别单词边界。

在像 bash 这样的 shell 中尝试这个(其他 shell 可能会以不同的方式处理这个问题,例如 zsh):

mystring="foo:bar baz rab"
for word in $mystring; do
  echo "Word: $word"
done

的默认值IFS由空白字符组成(准确地说:空格、制表符和换行符)。每个字符都可以是一个单词边界。因此,使用默认值IFS,上面的循环将打印:

Word: foo:bar
Word: baz
Word: rab

换句话说,shell 认为空格是单词边界。

现在,尝试IFS=:在执行循环之前进行设置。这次的结果是:

Word: foo
Word: bar baz rab

现在,shellmystring也分裂成单词 - 但现在,它只将冒号视为单词边界。

的第一个字符IFS是特殊的:它用于在使用特殊$*变量时分隔输出中的单词(示例取自高级 Bash 脚本编写指南,您还可以在其中找到有关此类特殊变量的更多信息):

$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z

相比于:

$ bash -c 'set w x y z; IFS="-:;"; echo "$*"'
w-x-y-z

请注意,在这两个示例中,shell 仍会将所有字符:,-;视为单词边界。唯一改变的是 的行为$*

另一件重要的事情是要知道所谓的“IFS 空白”是如何实现的被治疗。基本上,一旦IFS包含空格字符,在处理字符串之前,就会从要拆分的字符串中删除前导和尾随空格,并且顺序连续的空白字符也分隔字段。但是,这仅适用于实际存在于 中的那些空白字符IFS

例如,让我们看一下字符串(尾随空格以及和"a:b:: c d "之间的两个空格字符)。cd

  1. 它将IFS=:被分成四个字段:"a""b"""(空字符串)和(同样,和" c d "之间有两个空格)。请注意最后一个字段中的前导和尾随空格。cd
  2. 使用 时IFS=' :',它将分为五个字段:"a""b"""(空字符串)"c""d"。任何地方都没有前导和尾随空格。

请注意,在第二个示例中,多个连续的空白字符如何分隔两个字段,而多个连续的冒号则不然(因为它们不是空白字符)。

至于IFS=$'\n',这是、和FreeBSDksh93也支持的语法(在所有 shell 之间都有变化)。引用 bash 手册页:bashzshmkshsh

$'string' 形式的单词会被特殊处理。该单词扩展为“字符串”,并按照 ANSI C 标准指定的方式替换反斜杠转义字符。

\n是换行符的转义序列,因此IFS最终被设置为单个换行符。

答案2

在美元单引号内,某些字符会被特殊评估。例如,\n被转换为新行。

因此,这一行将换行符分配给变量 IFS。反过来,IFS 是 bash 中的一个特殊变量:内部字段分隔符。正如man bash所说,它

用于扩展后的单词分割,并使用read内置命令将行分割成单词。默认值为<space><tab><newline>

答案3

简而言之,IFS=$'\n'将换行符分配\n给变量IFS

$'string'构造是一种引用机制,用于解码类似转义序列的 ANSI C。此语法来自ksh93,并且可移植到现代 shell,如bash, zsh, pdksh, busybox sh

此语法不是由 POSIX 定义的,但已被接受SUS第7期

答案4

$IFS我更喜欢通过示例来解释:
Suppsoe 你想要 cp 或 mv 或其他文件处理,IFS 默认为空,当你的文件有元字符或空格,例如 :
Linux Administration.pdfFree Software Fundation.ogg,当然你会有问题,因为:Linux 考虑seperate param 和 Administration 考虑一个单独的 param。所以 bash 有built-in variable,那么你可以初始化为IFS==$(echo -en "\n\b"),然后 bash 丢弃文件名之间的任何元字符和空格,例如:

#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
mymusicdir=~/test/dd
find $mymusicdir -name "*" -execdir rename 's/ /_/g' "{}" +
IFS=$SAVEIFS

相关内容