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 "
之间的两个空格字符)。c
d
- 它将
IFS=:
被分成四个字段:"a"
、"b"
、""
(空字符串)和(同样,和" c d "
之间有两个空格)。请注意最后一个字段中的前导和尾随空格。c
d
- 使用 时
IFS=' :'
,它将分为五个字段:"a"
、"b"
、""
(空字符串)"c"
和"d"
。任何地方都没有前导和尾随空格。
请注意,在第二个示例中,多个连续的空白字符如何分隔两个字段,而多个连续的冒号则不然(因为它们不是空白字符)。
至于IFS=$'\n'
,这是、和FreeBSDksh93
也支持的语法(在所有 shell 之间都有变化)。引用 bash 手册页:bash
zsh
mksh
sh
$'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.pdf
或Free 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