Abd*_*red 230 command-line bash shell-script
bash shell 脚本的开头是以下行:
IFS=$'\n'
Run Code Online (Sandbox Code Playgroud)
这组符号背后的含义是什么?
Tbl*_*lue 273
IFS代表“内部字段分隔符”。shell 使用它来确定如何进行分词,即如何识别单词边界。
在像 bash 这样的 shell 中试试这个(其他 shell 可能会以不同的方式处理这个,例如 zsh):
mystring="foo:bar baz rab"
for word in $mystring; do
echo "Word: $word"
done
Run Code Online (Sandbox Code Playgroud)
的默认值IFS由空白字符组成(准确地说:空格、制表符和换行符)。每个字符可以是一个词边界。因此,使用默认值IFS,上面的循环将打印:
mystring="foo:bar baz rab"
for word in $mystring; do
echo "Word: $word"
done
Run Code Online (Sandbox Code Playgroud)
换句话说,shell 认为空格是单词边界。
现在,IFS=:在执行循环之前尝试设置。这次的结果是:
Word: foo:bar
Word: baz
Word: rab
Run Code Online (Sandbox Code Playgroud)
现在,shell 也拆分mystring为单词——但现在,它只将冒号视为单词边界。
的第一个字符IFS是特殊的:它用于在使用特殊$*变量时分隔输出中的单词(示例取自Advanced Bash Scripting Guide,您还可以在其中找到有关此类特殊变量的更多信息):
$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z
Run Code Online (Sandbox Code Playgroud)
相比于:
$ bash -c 'set w x y z; IFS="-:;"; echo "$*"'
w-x-y-z
Run Code Online (Sandbox Code Playgroud)
请注意,在这两个示例中,shell 仍会将所有字符:,-和;视为单词边界。唯一改变的是 的行为$*。
另一个需要了解的重要事情是如何处理所谓的“IFS 空白” 。基本上,只要IFS包含空格字符,前导和尾随空格就会在处理之前从要拆分的字符串中剥离,并且一系列连续的空格字符也会分隔字段。但是,这仅适用于实际存在于IFS.
例如,让我们看看在字符串"a:b:: c d "(尾随空间和之间有两个空格字符c和d)。
IFS=:将它分为四个领域:"a","b",""(空字符串)和" c d "(再次,两者之间的空间c和d)。请注意最后一个字段中的前导和尾随空格。IFS=' :',它将被拆分为五个字段:"a"、"b"、""(空字符串)"c"和"d"。任何地方都没有前导和尾随空格。请注意在第二个示例中多个连续的空格字符如何分隔两个字段,而多个连续的冒号则不然(因为它们不是空格字符)。
至于IFS=$'\n',这是一个ksh93语法也通过支持bash,zsh,mksh和FreeBSD sh(所有壳之间有变化)。引用 bash 联机帮助页:
$'string' 形式的词被特殊处理。该词扩展为“字符串”,并按照 ANSI C 标准的规定替换反斜杠转义字符。
\n是换行符的转义序列,因此IFS最终被设置为单个换行符。
cho*_*oba 29
在带美元的单引号内,一些字符被特别评估。例如,\n被转换为新行。
因此,此特定行将换行符分配给变量 IFS。反过来,IFS 是 bash 中的一个特殊变量:内部字段分隔符。正如man bash所说,它
用于扩展后的分词,并使用
read内置命令将行拆分为单词。默认值为<space><tab><newline>。
cuo*_*glm 21
简而言之,IFS=$'\n'将换行符分配\n给变量IFS。
$'string'构造是一种引用机制,用于像转义序列一样解码 ANSI C。这种语法来自ksh93,并且可以移植到现代 shell 中,例如bash, zsh, pdksh, busybox sh。
此语法不是由 POSIX 定义的,但已被SUS issue 7接受。