bash shell脚本的开头是以下行:
IFS=$'\n'
这些符号集合的含义是什么?
bash shell脚本的开头是以下行:
IFS=$'\n'
这些符号集合的含义是什么?
Answers:
IFS代表“内部字段分隔符”。外壳使用它来确定如何进行单词拆分,即如何识别单词边界。
在像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
换句话说,外壳认为空白是一个单词边界。
现在,IFS=:在执行循环之前尝试设置。这次,结果是:
Word: foo
Word: bar baz rab
现在,shell mystring也会拆分为单词-但现在,它仅将冒号视为单词边界。
第一个字符IFS是特殊字符:使用特殊$*变量时,它用于在输出中定界(例如,摘自Advanced Bash Scripting Guide的示例,在该示例中,您还可以找到有关特殊变量的更多信息):
$ 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',这是一个ksh93语法也通过支持bash,zsh,mksh和FreeBSD sh(所有壳之间有变化)。引用bash手册页:
$'string'形式的单词经过特殊处理。该单词扩展为“字符串”,并按ANSI C标准的规定替换反斜杠转义字符。
\n是换行符的转义序列,因此IFS最终被设置为单个换行符。
bash脚本指南或其他内容相比,阅读和理解POSIX规范要好得多。基本上,在这样的链接上可用的信息缺少重要的方式。无论如何,因此错过了有关外壳拆分的两个关键点-globbing和IFS空白。
unset IFS使Shell行为与完全不同IFS=。此外,IFS中的第一个字节也很特殊"${named_array[*]}"-但在未引用扩展名时也
$IFS是在列表上下文中扩展未引用变量时执行的两个主要操作之一(这split是split+glob运算符的一部分)。另一个正在徘徊。使用工作分割时,通常需要发出set -f禁用该glob零件的命令。
$IFS也使用3read
在用美元括起来的单引号内,某些字符会被特别评估。例如,\n被翻译为换行符。
因此,此特定行将换行符分配给变量IFS。IFS又是bash中的一个特殊变量:内部字段分隔符。至于man bash说,这
用于扩展后的单词拆分,并使用
read内置命令将行拆分为单词。默认值为<space><tab><newline>。
dollared single quotes与单引号不同。
我更喜欢$IFS通过示例进行解释:
Suppsoe您要进行cp或mv或其他文件处理,IFS通过defualt为空,当您的文件包含meta char或空间(如:
Linux Administration.pdf或)时Free Software Fundation.ogg,请确保您具有探针,因为:Linux考虑单独的参数和Administartion考虑单独的参数.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