| Parameter | Details |
|---|---|
| IFS | 内部字段分隔符 |
-x |
执行命令时打印命令及其参数(Shell 选项) |
Section 45.1: 内容、时间和原因?
当 shell 执行参数扩展、命令替换、变量或算术扩展时,它会扫描结果中的字边界。如果发现任何字边界,就会在该位置将结果分割成多个字。字边界由 shell 变量 IFS(内部字段分隔符)定义。IFS 的默认值是空格、制表符和换行符,也就是说,如果没有明确阻止,单词分割将在这三个空白字符上发生。
set -x
var='I am
a
multiline string'
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
在上例中,fun 函数就是这样执行的:
fun I am a multiline string
将
$var分割为 5 个参数,只打印 I、am 和 a。
Section 45.2: 分词的不良影响
$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = $a ]被解释为[ I am a string with spaces = I am a string with spaces ]。[是测试命令,其中I am a string with spaces不是一个参数,而是 6 个参数!"!
$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = something ]被解释为[ I am a string with spaces = something ]
$ [ $(grep . file) = 'something' ]
bash: [: too many arguments
grep命令返回的是一个带空格的多行字符串,所以你可以想象有多少个参数......
Section 45.3: 分词的作用
在某些情况下,分词很有用:
填充数组:
arr=($(grep -o '[0-9]\+' file))
这将用文件中找到的所有数值填满
arr
循环使用空格分隔的单词:
words='foo bar baz'
for w in $words;do
echo "W: $w"
done
输出:
W: foo
W: bar
W: baz
传递不包含空格的空格分隔参数:
packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs
或者
packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs
这将安装软件包。如果用双引号包含
$packs,则会出错。Unquoetd
$packs将所有空格分隔的软件包名称作为参数发送给apt-get,而引用时会将$packs字符串作为单个参数发送,然后apt-get会尝试安装一个名为apache2 php php-mbstring php-mysql(第一个)的软件包,而这个软件包显然并不存在。
Section 45.4: 按分隔符分割的变化
我们可以简单地将分隔符从空格替换为新行,如下例所示。
echo $sentence | tr " " "\n"
它将分割变量句子的值,并逐行显示。
Section 45.5: 使用 IFS 进行拆分
为了更清楚起见,让我们创建一个名为 showarg 的脚本:
#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo
现在让我们看看它们的区别:
$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var分成 4 个 args。IFS 是空格字符,因此单词分割发生在空格中
$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>
在上文中,由于没有找到 IFS 字符,所以没有进行分词。
现在让我们设置 IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var` 被分成 4 个参数,而不是一个参数。
Section 45.6: IFS 和分词
让我们将 IFS 设置为空格字符:
set -x
var='I am
a
multiline string'
IFS=' '
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
这次分词只对空格有效。fun 函数将这样执行
fun I 'am
a
multiline' string
$var分成 3 个参数。I, am\na\nmultiline 和字符串将被打印出来
让我们将 IFS 设置为仅换行:
IFS=$'\n'
...
现在,有趣的事情即将发生:
fun 'I am' a 'multiline string'
$var分成 3 个参数。我是,将打印一个多行字符串
让我们看看将 IFS 设置为 nullstring 会发生什么:
IFS=
...
这一次,我们将这样来玩:
fun 'I am
a
multiline string'
$var没有被拆分,即它仍然是一个 arg。
可以通过将 IFS 设置为 nullstring 来防止分词。
防止分词的一般方法是使用双引号:
fun "$var"
将在上述所有情况下防止分词,即执行 fun 函数时只有一个参数。