linux shell中for循环,如何读取整一行

在处理一个多行数据的过程中,使用for循环去读取每行数据,结果发现输出是

[Sam@localhost 20220927-temp]$ more temp.list
aaa     bbb     ccc
ddd     eee     fff
ggg     hhh     iii
[Sam@localhost 20220927-BA]$ for i in `cat temp.list`;do echo $i;done
aaa
bbb
ccc
ddd
eee
fff
ggg
hhh
iii

shell中for循环的默认分隔符是:空格、tab、\n

一、若shell for 循环以\n作为分隔符,输出整行

方式一:

#! /bin/bash

IFS=$'\n'
for i in `cat emp.list`
do 
  echo $i
done

运行时使用./aa.sh 或者bash aa.sh。 不能使用sh aa.sh。

IFS="\n" # 将字符n作为IFS的换行符。
IFS=$"\n" # 这里\n确实通过$转化为了换行符,但仅当被解释时(或被执行时)才被转化为换行符;第一个和第二个是等价的
IFS=$'\n' # 这才是真正的换行符。

方式二:

#! /bin/bash
while read i
do 
  echo $i
done 

二、若shell循环,读取每行第二列,列之间以tab分隔

方法一:

开始时使用read 定义tab键的方式不成功


$ while read i; do a=`echo $i|cut -f2 -d '       '`; echo $a;done 

转换为"$i" 则可成功,是因为echo $i会将默认tab或者空格作为分隔符的默认输出为空格,若管道后的命令的分隔符为\t,则不会按要求分割。

$ while read i; do a=`echo "$i"|cut -f2 -d '       '`; echo $a;done 

cut 的tab分隔符有两种方式:(1)先ctrl+v,然后按tab键,记得用单引号引起来;(2)使用$'\t'。

方法二:

可以使用将行存入数组的方式调取数组的第二个元素,但要确保每列使用同样的分隔符,若既有空格又有tab键分隔符,则会出现混乱
$ while read line;do a=($line); echo ${a[1]};done 

##################################################################################################

环境变量IFS,成为内部字段分隔符(internal field seperator),定义了bash shell 用作字段分隔符的一系列字符。默认情况下,bash shell会将下列字符当作字段分隔符

  • 空格
  • 制表符 tab键
  • 换行符 \n

可使用以下命令查看当前默认的IFS

$ echo "$IFS" | od -b  
0000000 040 011 012 012  
0000004

或者
$ set |grep IFS
IFS=$' \t\n'

直接输出IFS是看不到的,把它转化为二进制就可以看到了,"040"是空格,"011"是Tab,"012"是换行符"\n" 。最后一个 012 是因为 echo 默认是会换行的。

若单行数据中有空格时,使用for循环读取每一行,由于空格为默认的字段分隔符,bash shell 遇到空格,就认为读取到一个新的字段,会出现问题。此时需要在shell脚本中临时改变环境变量IFS的值来限制被bash shell当作字符段的字符,如修改为IFS=$'\n'IFS=$'\t'

但是修改完IFS后,如何恢复IFS默认值?
答: 方法一:简单粗暴,直接关闭当前终端。(经测试若修改只影响当前终端窗口)
方法二:可以在修改IFS之前保存原来的IFS值,之后在恢复它,以防忘记,后续出现奇奇怪怪的显示。如下所示:

IFS_old=$IFS
IFS=$'\n'
#在接下来的代码中使用新的IFS
#code
#使用完毕后恢复IFS原来的值
IFS=$IFS_old

答:方式三:在终端输入IFS=$' \t\n',即将是恢复为空格、tab键、和换行符作为分隔符。

##################################################################################################

while read line是一次性将一行的文件信息读入并赋值给变量line。当文件中有多行文字,在while循环中再一次调用read语句,就会读取到下一条记录。而$line中的最后一行读完,无法获取下一行记录,从而退出while循环。

for是每次读取文件中一个以空格为分隔符的字符串。

你可能感兴趣的:(linux shell中for循环,如何读取整一行)