01 背景写这一篇文章源于在工作遇到了一个比较有趣的问题,我在写shell脚本的时候,发现echo的结果和预期不一致。具体如下:
我有一个文件,文件中有两列,假设文件test.txt内容如下:
a 1
b 2
c 3
d 4
此时我想通过循环,将每一列的值显示出来
for line in `cat test.txt`; do echo $line ;done
预期的结果是:
a 1
b 2
c 3
d 4
实际的结果是:
我尝试过将变量使用双引号引起来,但显示还是这样:
使用echo -n 不还换行?显示如下:
经过了诸多尝试都不行,很明显echo将空格作为了分隔符,并将分隔符前后的数据换行输出,那么这个分隔符是否可以自定义呢?
02 IFS的作用和含义
经过查找,发现Bash IFS变量是干这个事的,先来一波来自百度的介绍:
在Bash Shell中,IFS(Internal Field Separator)是一个环境变量,用于指定字段分隔符。当您从命令行或文件中读取文本行时,IFS变量定义了如何将文本行拆分成字段。
IFS变量默认情况下包含空格、制表符和换行符。这意味着当您从命令行或文件中读取文本行时,默认情况下,IFS会将文本行拆分成多个字段,每个字段之间由空格、制表符或换行符分隔
即默认情况下,IFS会将文本行拆分成多个字段,每个字段之间由空格、制表符或换行符分隔。
也可使用man bash,搜索IFS,定义如下:
IFS 内部字段分隔符 Internal Field Separator 用来在扩展之后进行分词,使用内部命令 read 将行划分成词。默认值是 ``<space><tab><newline>''
可以看出IFS的默认值是一个由空格、制表符和换行符组成的三字符字符串,可通过以下命令进行验证:
[root@txy201-51 tmp]# echo "$IFS" | cat -et
^I$
$
[root@txy201-51 tmp]#
当我们指定只使用换行符作为分割符的时候,这个问题得以解决:
但是在默认情况下while 一个变量读取一行,如果有多个变量就以空格为分隔符:当我们存在以下文件:
John 25 65.4
Mary 30 58.2
while只有一个变量时:
while有两个变量时:
while有三个变量时:
变量数量超出列时,显示空
总之,我们可以巧妙地利用IFS参数,编写更为简洁的脚本,如在while中指定IFS的方式: