bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
bash下的很多命令都會分割單詞,絕大多數時候默認是采用空格作為分隔符,有些時候遇到制表符、換行符也會進行分隔。最典型的是"for i in a b c",它會分割變量列表"a b c"使其成為三個變量。這種分隔符是由IFS變量指定的。
IFS是bash內部字段分隔符的環境變量。
[root@xuexi ~]# set | grep IFS IFS=$' \t\n'
默認的IFS在碰到空格、制表符\t和分行符\n就會自動分隔進入下一步。但是對空格處理有點不一樣,對行首和行尾兩邊的空格不處理,並且多個連續的空格默認當作一個空格。
有些時候在編寫腳本或執行循環的時候,修改IFS可以起很大作用。如果要修改IFS,最好記得先備份系統IFS,再需要的地方再還原IFS。
例如:
[root@xuexi ~]# data="name,sex,rollno,location" [root@xuexi ~]# oldIFS=$IFS # 備份IFS到變量oldIFS [root@xuexi ~]# IFS=$',' # 將IFS設置為逗號,便於做data的分隔符 [root@xuexi ~]# for item in $data;do echo Item:$item;done Item:name Item:sex Item:rollno Item:location
[root@xuexi ~]# IFS=$oldIFS # 最后將IFS還原
可以看到,上面的示例將默認分隔符設置為了逗號后,不用處理data變量就可以輕松划分字段了。
再來一個有趣的示例:逐字符打印各個字符。
cat /etc/resolv.conf | (IFS=$'\034';while read -N 1 x;do /usr/bin/printf "%s" "$x";sleep 0.1; done)
上面的while read -N 1 x表示每次讀取一個字符並保存到變量x中,因為可能讀取到空格或換行符,使得printf輸出時無法輸出,所以修改了IFS的值,將其設置為"\034",這是一個控制字符,不可能出現在文件中,所以對文件中任何一個字符都很安全。
大多數時候,我們都不會去修改IFS也不會想到通過修改IFS來達到某種目的,而是采用其他方法來替代實現。這樣就需要注意默認IFS(" \t\n")的一個特殊性,它會忽略前導空白和后綴空白,並壓縮連續空白。在某些時候,這會出現意想不到的問題。
例如:
[root@xuexi ~]# a=-s" " [root@xuexi ~]# echo "$a" | wc -m 4
實際上這里的$a是3個字符組成的,最后一個字符為空格。如果不對變量加引號,那么很多情況下都會出現問題:
[root@xuexi ~]# echo $a | wc -m # s后面的空格被忽略了 3 [root@xuexi ~]# echo "${a:2}" | wc -m # 截取到了s后面的空格 2 [root@xuexi ~]# echo ${a:2} | wc -m # 沒有截取到s后面的空格 1 [root@xuexi ~]# expr substr $a 3 100 | wc -m # 沒有截取到s后面的空格 1 [root@xuexi ~]# expr substr "$a" 3 100 | wc -m # 截取到了s后面的空格 2
因此,在可以對變量加引號的情況下,盡100個可能地加上引號來保護空白字符。