一、IFS 介绍
Shell 脚本中有个变量叫 IFS(Internal Field Seprator) ,内部域分隔符。完整定义是The shell uses the value stored in IFS,
which is the space, tab, and newline characters by default, to delimit words for the read and set commands, when parsing output from command substitution, and when performing variable substitution.
Shell 的环境变量分为 set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set
变量里包含了 env 变量,但 set 变量不一定都是 env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。
而 IFS 是一种 set 变量,当 shell 处理"命令替换"和"参数替换"时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。 二、IFS 简单实例 1、查看变量 IFS 的值。
$ IFS=:;
$ set x y z
$ echo $*
x y z
$ echo "$*"
x:y:z
$ echo $@
x y z
$ echo "$@"
x y z 上例 set 变量其实是3个参数,而下面这个例子实质是2个参数,即 set "x y z" 和 set x y z 是完全不同的。
$ set "x" "y z"
$ echo $*
x y z
$ echo "$*"
x:y z
$ echo $@
x y z
$ echo "$@"
x y z
$ echo $* |od -b
0000000 170 040 171 040 172 012
0000006
$ echo "$*" |od -b
0000000 170 072 171 040 172 012
0000006
小结:$* 会根据 IFS 的不同来组合值,而 $@ 则会将值用" "来组合值! 3、for 循环中的奇怪现象
$ for x in $var ;do echo $x |od -b ;done
0000000 012
0000001
0000000 040 141 012
0000003
0000000 142 012
0000002
0000000 012
0000001
0000000 143 012
0000002
先暂且不解释 for 循环的内容!看下面这个输出!IFS 的值同上! var=": a:b::c:",
$ IFS=:
$ var=ab::cd
$ echo $var
ab cd
$ echo "$var"
ab::cd解释下:x 的值是 "ab::cd",当进行到 echo $x 时,因为$符,所以会进行变量替换。Shell 根据 IFS 的值将 x 分解为 ab "" cd,然后echo,插入空隔,ab[space]""[space]cd,忽略"",输出 ab cd 。
Example 2 :
$ read a
xy z
$ echo $a
xy z
解释:这是 http://bbs.iyunv.com/thread-207178-1-1.html 上的一个例子。此时IFS是默认值,本希望把所有的输入(包括空格)都放入变量a中,但是输出的a却把前面的空格给忽略了!!原因是:默认的 IFS 会按 space tab newline 来分割。这里需要注意的一点是,read
命令的实现过程,即在读入时已经替换了。解决办法是在开头加上一句 IFS=";" ,这里必须加上双引号,因为分号有特殊含义。 Example 3 :
#!/bin/bash
IFS_old=$IFS #将原IFS值保存,以便用完后恢复
IFS=$’\n’ #更改IFS值为$’\n’ ,注意,以回车做为分隔符,IFS必须为:$’\n’
for i in $((cat pwd.txt)) #pwd.txt 来自这个命令:cat /etc/passwd >pwd.txt
do
echo $i
done
IFS=$IFS_old #恢复原IFS值另外一个例子,把IP地址逆转输出:
Example 5 :
#!/bin/bash
IP=220.112.253.111
IFS="."
TMPIP=$(echo $IP)
IFS=" " # space
echo $TMPIP
for x in $TMPIP ;do
Xip="${x}.$Xip"
done
echo ${Xip%.} Complex_Example 1: http://bbs.iyunv.com/forum.php?mod=viewthread&tid=3660898&page=1#pid21798049
function output_args_ifs(){
echo "=$*"
echo "="$*
for m in $* ;do
echo "[$m]"
done
}
IFS=':'
var='::a:b::c:::'
output_args_ifs $var
输出为:
=::a:b::c:: # 少了最后一个冒号!看前面就知道为什么了
= a b c
[]
[]
[a]
[]
[c]
[]
由于 "output_args_ifs $var" 中 $var 没有加引号,所以根据IFS替换!根据IFS划分出变量: "" "" "a" "b" "" "c" "" ""(可以通过输出 $# 来测试参数的个数!),重组的结果为
"$@" 的值是 "" [space] "" [space] "a" [space] "b" [space] "" [space] "c" [space] "" [space] "",可以通过,echo==>" a b c "