Shell脚本中有个变量叫 IFS(Internal Field Seprator),内部域分隔符。
完整定义:
The shell uses the value stored in IFS, which is the space, tab, and newlinecharacters 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 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。
# STRING1="111 222 333 444"
# echo $STRING1
# echo "$STRING1"
这组代码没什么好说的,输出的是:111 222 333 444,它的作用是和下面那段做对比!
# STRING2="111 222 333 444"
# echo $STRING2
# echo "$STRING2"
输出的结果是
111 222 333 444
111 222 333 444
为什么?
第一个输出的结果明显不对,难道输出了的是STRING1的值,明显不可能,这就是IFS的鬼伎俩!
首先介绍一下这个家伙,IFS是shell内定的一个变量,默认定义的值为 3个,不好意思,这3个值我打出来也看不见,只能写英文。
那IFS的作用是什么了,它的作用就是把字符串里的某某字符(和它一样的字符,例如上面的)转义成分隔符。
例如"111 222 333 444",这个字符串其实就是 111222333444
因为IFS里也有个空格,所以在它眼中就是分隔符,所以"111 222 333 444"在它看来就是这个鬼样子111222333< 分隔符>444
分隔符(不是所有的分隔符都会合并,空格是个例外)进行合并,所以就成了111222333444,而这该死的偏偏显示出来和一个空格是一样的(或者说空格被用来表示分隔符),所以显示出来就变成了"111 222 333 444"。
最终,你 echo $STRING2 显示出来的是"111 222 333 444",echo "$STRING2"之所以还是保持原样是因为""它屏蔽了IFS的功能!
如果我这样改下,将分隔符改成& ,结果就一样了,这时候shell就不会认为空格是分隔符了,倒是&符号要倒霉了 !
# IFS='&'
# STRING2="111 222 333 444"
# echo $STRING2
111 222 333 444
# echo "$STRING2"
111 222 333 444
$* 指的是脚本入口参数的字符串集,是一个全局变量
你在终端输入一个脚本,带了3个参数:
# ./script 111 222 333
那么 echo $* 输出的就是111 222 333,这没什么问题,但是下面的东西就又忽悠人了!
首先是这段代码:
# IFS='&'
# STRING2="111&222&&333&&&444"
# echo $STRING2
# echo "$STRING2"
输出的是
111 222 333 444
111&222&&333&&&444
经过上面的解释,就不难理解了
因为IFS='&',所以字符串里的&全成了分隔符,所以第一个输出的是 111 222 333 444
现有一组代码,在终端运行:
# ./script 111 222 333 444
########################
IFS='&'
echo $*
echo "$*"
#########################
输出的是:
111 222 333 444
111&222&333&444
因为$*等于111IFS222IFS333IFS444,亦等于111&222&333&444
echo $* 时,&代表分隔符,所以要转换成空格 ,而第二行由于双引号 "" 的作用使得&没有进行转换。
参考
详解shell中的IFS变量
https://blog.csdn.net/guyongqiangx/article/details/80220434
Shell中的IFS解惑
https://blog.csdn.net/whuslei/article/details/7187639
shell 中IFS分隔符
http://xstarcd.github.io/wiki/shell/IFS.html
关于read命令的一个小问题
http://bbs.chinaunix.net/thread-207178-1-1.html
Linux read 命令
http://www.runoob.com/linux/linux-comm-read.html