(4)awk读取行的细节

详细分析awk如何读取文件

awk读取输入文件时,每次读取一条记录(record)(默认情况下按行读取,所以此时记录就是行)。每读取一条记录,将其保存到$0中,然后执行一次main代码段。

[root@docker-01 ~]# awk '{print $0}' a.txt

如果是空文件,则因为无法读取到任何一条记录,将导致直接关闭文件,而不会进入main代码段。

[root@docker-01 ~]# touch x.log
[root@docker-01 ~]# awk '{print $0}' x.log 

可设置表示输入记录分隔符的预定义变量RS(Record Separator)来改变每次读取的记录模式。

# RS="\n" 、 RS="m"
[root@docker-01 ~]# awk 'BEGIN{RS="\n"}{print $0}' a.txt
ID  name    gender  age  email          phone
1   Bob     male    28   abc@qq.com     18023394012
2   Alice   female  24   def@gmail.com  18084925203
3   Tony    male    21   aaa@163.com    17048792503
4   Kevin   male    21   bbb@189.com    17023929033
5   Alex    male    18   ccc@xyz.com    18185904230
6   Andy    female  22   ddd@139.com    18923902352
7   Jerry   female  25   exdsa@189.com  18785234906
8   Peter   male    20   bax@qq.com     17729348758
9   Steven  female  23   bc@sohu.com    15947893212
10  Bruce   female  27   bcbd@139.com   13942943905
[root@docker-01 ~]# awk 'BEGIN{RS="m"}{print $0}' a.txt
ID  na
e    gender  age  e
ail          phone
1   Bob     
ale    28   abc@qq.co
     18023394012
2   Alice   fe
ale  24   def@g
ail.co
  18084925203
3   Tony    
ale    21   aaa@163.co
    17048792503
4   Kevin   
ale    21   bbb@189.co
    17023929033
5   Alex    
ale    18   ccc@xyz.co
    18185904230
6   Andy    fe
ale  22   ddd@139.co
    18923902352
7   Jerry   fe
ale  25   exdsa@189.co
  18785234906
8   Peter   
ale    20   bax@qq.co
     17729348758
9   Steven  fe
ale  23   bc@sohu.co
    15947893212
10  Bruce   fe
ale  27   bcbd@139.co

RS通常设置在BEGIN代码块中,因为要先于读取文件就确定好RS分隔符。

RS指定输入记录分隔符时,所读取的记录中是不包含分隔符字符的。例如RS="a",则$0中一定不可能出现字符a。

RS可能两种情况

RS为单个字符:直接使用该字符来分割记录
RS为多个字符:将其当作正则表达式,只要匹配正则表达式的符号,都用来分割记录
  设置预定义变量IGNORECASE为非零值,正则匹配时表过忽略大小写,
  兼容模式下,只有首字符才生效,下面使用正则模式去分割记录。

特殊的RS值用来解决特殊读取需求:

RS="":按段落读取
RS="\0":一次性读取所有数据,但有些特殊文件中包含了空字符\0
RS="^$":真正的一次性读取所有数据,因为非空文件不可能匹配成功
RS="\n+":按行读取,但忽略所有空行

示例:

# 按段落读取:RS=''
[root@docker-01 ~]# awk 'BEGIN{RS=""} {print $0"------"}' a.txt 
ID  name    gender  age  email          phone
1   Bob     male    28   abc@qq.com     18023394012
2   Alice   female  24   def@gmail.com  18084925203
3   Tony    male    21   aaa@163.com    17048792503
4   Kevin   male    21   bbb@189.com    17023929033
5   Alex    male    18   ccc@xyz.com    18185904230
6   Andy    female  22   ddd@139.com    18923902352
7   Jerry   female  25   exdsa@189.com  18785234906
8   Peter   male    20   bax@qq.com     17729348758
9   Steven  female  23   bc@sohu.com    15947893212
10  Bruce   female  27   bcbd@139.com   13942943905------
# 一次性读取所有数据:RS='\0' RS="^$"
[root@docker-01 ~]# awk 'BEGIN{RS='\0'}{print $0"------"}' a.txt  
ID  name    gender  age  email          phone
1   Bob     male    28   abc@qq.com     18------
23394------
12
2   Alice   female  24   def@gmail.com  18------
849252------
3
3   Tony    male    21   aaa@163.com    17------
487925------
3
4   Kevin   male    21   bbb@189.com    17------
23929------
33
5   Alex    male    18   ccc@xyz.com    181859------
423------

6   Andy    female  22   ddd@139.com    189239------
2352
7   Jerry   female  25   exdsa@189.com  187852349------
6
8   Peter   male    2------
   bax@qq.com     17729348758
9   Steven  female  23   bc@sohu.com    15947893212
1------
  Bruce   female  27   bcbd@139.com   139429439------
5
------
[root@docker-01 ~]# awk 'BEGIN{RS="^$"}{print $0"------"}' a.txt
ID  name    gender  age  email          phone
1   Bob     male    28   abc@qq.com     18023394012
2   Alice   female  24   def@gmail.com  18084925203
3   Tony    male    21   aaa@163.com    17048792503
4   Kevin   male    21   bbb@189.com    17023929033
5   Alex    male    18   ccc@xyz.com    18185904230
6   Andy    female  22   ddd@139.com    18923902352
7   Jerry   female  25   exdsa@189.com  18785234906
8   Peter   male    20   bax@qq.com     17729348758
9   Steven  female  23   bc@sohu.com    15947893212
10  Bruce   female  27   bcbd@139.com   13942943905
------
# 忽略空行:RS='\n+'
[root@docker-01 ~]# awk 'BEGIN{RS="\n+"}{print $0"------"}' a.txt 
ID  name    gender  age  email          phone------
1   Bob     male    28   abc@qq.com     18023394012------
2   Alice   female  24   def@gmail.com  18084925203------
3   Tony    male    21   aaa@163.com    17048792503------
4   Kevin   male    21   bbb@189.com    17023929033------
5   Alex    male    18   ccc@xyz.com    18185904230------
6   Andy    female  22   ddd@139.com    18923902352------
7   Jerry   female  25   exdsa@189.com  18785234906------
8   Peter   male    20   bax@qq.com     17729348758------
9   Steven  female  23   bc@sohu.com    15947893212------
10  Bruce   female  27   bcbd@139.com   13942943905------
# 忽略大小写:预定义变量IGNORECASE设置为非0值
[root@docker-01 ~]# awk 'BEGIN{IGNORECASE=1}{print $0"------"}' RS='[ab]' a.txt 
ID  n------
me    gender  ------
ge  em------
il          phone
1   ------
o------
     m------
le    28   ------
------
c@qq.com     18023394012
2   ------
lice   fem------
le  24   def@gm------
il.com  18084925203
3   Tony    m------
le    21   ------
------
------
@163.com    17048792503
4   Kevin   m------
le    21   ------
------
------
@189.com    17023929033
5   ------
lex    m------
le    18   ccc@xyz.com    18185904230
6   ------
ndy    fem------
le  22   ddd@139.com    18923902352
7   Jerry   fem------
le  25   exds------
@189.com  18785234906
8   Peter   m------
le    20   ------
------
x@qq.com     17729348758
9   Steven  fem------
le  23   ------
c@sohu.com    15947893212
10  ------
ruce   fem------
le  27   ------
c------
d@139.com   13942943905
------
预定义变量RT:

在awk每次读完一条记录时,会设置一个称为RT的预定义变量,表示Record Termination。

当RS为单个字符时,RT的值和RS的值是相同的。

当RS为多个字符(正则表达式)时,则RT设置为正则匹配到记录分隔符之后,真正用于划分记录时的字符。

当无法匹配到记录分隔符时,RT设置为控制空字符串(即默认的初始值)。

awk 'BEGIN{RS="(fe)?male"}{print RT}' a.txt
[root@docker-01 ~]# awk 'BEGIN{RS="(fe)?male"}{print RT}' a.txt
male
female
male
male
male
female
female
male
female
female

两种行号:NR和FNR

在读取每条记录之后,将其赋值给$0,同时还会设置NR、FNR、RT。

  • NR:所有文件的行号计数器
  • FNR:是各个文件的行号计数器
[root@docker-01 ~]# awk '{print NR}' a.txt a.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@docker-01 ~]# awk '{print FNR}' a.txt a.txt
1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
[root@docker-01 ~]# 

 

posted @ 2020-03-01 12:49  星火撩原  阅读(424)  评论(0编辑  收藏  举报