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