zoukankan      html  css  js  c++  java
  • (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="
    " 、 RS="m"
    [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
    [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
    RS="^$":真正的一次性读取所有数据,因为非空文件不可能匹配成功
    RS="
    +":按行读取,但忽略所有空行

    示例:

    # 按段落读取: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='' 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='
    +'
    [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------
    # 忽略大小写:预定义变量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 ~]# 
  • 相关阅读:
    数据结构之 线性表 逆序简历链表
    数据结构之 线性表--顺序创建链表
    参观——校园招聘大会
    SDUT OJ 之 1571 《人品,有没有?》 字符串的处理问题
    青岛理工交流赛 H题 素数间隙
    青岛理工ACM交流赛 J题 数格子算面积
    STL版 括号匹配(感觉不如之前自己用数组模拟的跑的快)
    1076: [SCOI2008]奖励关( dp )
    BZOJ 1079: [SCOI2008]着色方案( dp )
    BZOJ 1984: 月下“毛景树”( 树链剖分 )
  • 原文地址:https://www.cnblogs.com/liujunjun/p/12389182.html
Copyright © 2011-2022 走看看