Linux文本处理之awk

GAWK:报告生成器,格式化文本输出

    awk [options] ‘program’ var=value file…

    awk [options] -f programfile var=value file…

    awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...


  awk程序组成部分:


    BEGIN语句块、能够使用模式匹配的通用语句块、END语句块


    选项:

      -F:指明输入时用到的字段分割符;

      -v var=value:自定义变量

      -f:指定awk脚本,从脚本中读取program


    基本格式:


      awk [options] 'program' file...

      program:pattern{action statements;...}  通常在单引号或双引号中;

      pattern与action:

        pattern部分决定动作语句何时触发及事件

          BEGIN:模式匹配之前要执行的动作


          END:模式匹配结束之后要执行的动作

        action statements对数据进行处理,放在{}内指明;

          print  $0,$!.......$(NF-1)........$NF(最后一列)


    分隔符,域,记录:


      awk执行时,由分隔符分隔的字段(域)标记$1,$2...$n称为域标识。$0为所有域。

      文件的每一行称为记录;

      省略action,则默认执行print $0的操作;




awk的工作原理:

  1)、执行BEGIN{action;...}语句块中的语句;

  2)、从文件或标准输入(stdin)读取一行,然后执行pattern{action;...}语句块,它会逐行扫描文件,从第一行到最后一行重复这个过程,知道文件被全部读取完毕;

  3)、当读至输入流末尾时,执行END{action;...}语句块


  BEGIN语句块:在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常 可以写在BEGIN语句块中。


  END语句块:在awk从输入流中读取完所有的行之后即被执行,比如 打印所有行的分析结果这类信息汇总都是在END语句块中完成它也是一个可选语句块

  pattern语句块中的通用命令是最重要的部分,也是可选的。如果 没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块                                                                                                                                                                                                                                                                                              

print格式:print item1,item2,...

      1)、逗号为分隔符;

      2)、输出的个item可以是字符串,也可以是当前记录的字段、变量或awk的表达式;

      3)、如省略item,相当于print $0;



     awk '{print "hello,awk"}'

     awk –F: '{print}' /etc/passwd         # -F指定分割符为  :冒号

     awk –F: '{print “wang”}' /etc/passwd


    awk –F: '{print $1}' /etc/passwd

    awk –F: '{print $0}' /etc/passwd

    awk –F: '{print $1”\t”$3}' /etc/passwd

    tail –3 /etc/fstab |awk '{print $2,$4}'


    变量:

      FS:输入字段分隔符,默认为空白字符;


1

awk -v FS=':' '{print $1,FS,$3}' file


      OFS:输出字段分隔符,默认为空白字符;指定输出时的分隔符是什么,一般可以进行分隔符号替换,类似下面的ORS的作用



      awk -v FS=':' -v OFS=':' '{print $1,$2,$3}' file

      [root@mysql-141 ~]# awk -v FS=':' -v OFS='#' '{print $1,$2,$3}' /etc/passwd

      root#x#0

      bin#x#1

      daemon#x#2

      adm#x#3




      RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效;


      awk -v RS=' ' '{print}' file


      ORS:输出记录分隔符,输出时用指定符号代替换行符;


      awk -v RS=' ' -v ORS='$$$' '{print}' file


      NF:字段数量



      awk -F: '{print NF}' file

      awk -F: '{print $(NF-1)}' file

      # 显示文件的第一列,第三列,倒数第二列和最后一列

        [root@mysql-141 ~]# awk -F : '{print $1,$2,$(NF-1),$NF}' /etc/passwd

        root x /root /bin/bash

        bin x /bin /sbin/nologin

        daemon x /sbin /sbin/nologin

        adm x /var/adm /sbin/nologin




      NR:行号


      awk -F: '{print NR,$1}' file   # 与FNR类似

      awk END'{print NR}' file

      [root@mysql-141 ~]# awk END'{print NR}' /etc/passwd  #将文件内容读取完成之后,统计行数

       26


      awk 'NR==2,NR==6{print NR,$0}}' file  #显示文件2-6行




      FNR:各文件的行号分别计数;



      awk -F: '{print FNR,$1}' file1 file2...

      [root@mysql-141 ~]# awk -F: '{print FNR,$1}' /etc/passwd

      1 root

      2 bin

      3 daemon

      4 adm

      5 lp

      6 sync

      7 shutdown

      8 halt




      FILENAME:当前文件名;文件内容有多少行,awk就会输出多少行


     awk '{print FILENAME}' FILE1 FILE2...

      [root@mysql-141 ~]# awk '{print FILENAME}' /etc/passwd |wc -l

      26

      [root@mysql-141 ~]# wc -l /etc/passwd

      26 /etc/passwd



      ARGV:数组,保存的是命令行所给定的各参数;


      awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab

      awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab

      [root@mysql-141 ~]# awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab      # 相当于shell里面的$1 $2 $3 的概念

      /etc/fstab

      [root@mysql-141 ~]# awk 'BEGIN {print ARGV[2]}' /etc/fstab /etc/inittab

      /etc/inittab

      [root@mysql-141 ~]# awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab

      awk

      [root@mysql-141 ~]# awk 'BEGIN {print ARGV[3]}' /etc/fstab /etc/inittab





    算术操作符:

      x+y x-y x*y x/y x^y x%y

      -x:转换为负数;

      +x:转换为数值,变量通过+连接运算,自动强制将字符串转为整形,非数字变成0,发现第一个非数字字符,后面的自动忽略;

字符串操作符:没有符号的操作符,字符串连接

    赋值操作符:


      =    +=    -=     *=      /=      %=     ^=      ++      --

    比较操作符:


      ==   !=   >    >=    <    <=



    模式匹配符:

      ~:左边的内容是否被右边的模式包含匹配


       !~:是否不匹配;


1

[root@mysql-141 ~]# awk -F: '$0 ~ /root/{print $1}' /etc/passwd    # 以:为分隔符,匹配全部内容包含root的行,打印第一列

       root

       operator


      [root@mysql-141 ~]# awk '$0 ~ "^root"' /etc/passwd       # 匹配所有内容,期初以root开头的行

       root:x:0:0:root:/root:/bin/bash


      [root@mysql-141 ~]# awk -F: '$3==0' /etc/passwd        # 匹配以冒号为分隔符,第三列是0的行

      root:x:0:0:root:/root:/bin/bash




cat >>/tmp/reg.txt<<EOF

Zhang    Dandan        41117397    :250:100:175

Zhang    Xiaoyu        390320151    :155:90:201

Meng    Feixue        80042789    :250:60:50

Wu    Waiwai        70271111    :250:80:75

Liu    Bingbing    41117483    :250:100:175

Wang    Xiaoai        3515064655    :50:95:135

Zi    Gege        1986787350    :250:168:200

Li    Youjiu        918391635    :175:75:300

Lao    Nanhai        918391635    :250:100:175

EOF

操作符:


      与&&


       或||


       非!



示例:

[root@mysql-141 ~]# awk -F : '$3>=0 && $3<=1000 {print $1}' /etc/passwd

root

bin

daemon

adm

lp


[root@mysql-141 ~]# awk -F : '$3==0 || $3>=1000 {print $1}' /etc/passwd

root




[root@mysql-141 ~]# awk -F : '!($3==0) {print $1}' /etc/passwd

bin

daemon

adm

lp


[root@mysql-141 ~]# awk -F : '!($3>=500) {print $3}' /etc/passwd

0

1

2

3

4

5

6




    awk PATTERN:

      1)、如果未指定:空模式,匹配每一行;

      2)、/regular expression/:仅处理能够被模式匹配到的行,需要用//括起来;


awk '/^UUID/{print $1}' /etc/passwd

awk '!/^UUID/{print $1}' /etc/passwd

      3)、relational expression:关系表达式,结果未"真"才会被处理;

        真:结果为非0值,非空字符串;

        假:结果为空字符串或0值;


awk -F : 'i=1;j=1{print i,j}' /etc/passwd

awk '!0' /etc/passwd ; awk '!1' /etc/passwd

awk –F : '$3>=1000{print $1,$3}' /etc/passwd

awk -F : '$3<1000{print $1,$3}' /etc/passwd

[root@mysql-141 ~]# awk -F : '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd

root /bin/bash

lipeng /bin/bash


[root@mysql-141 ~]# awk -F : '$NF ~ /nologin$/{print $1,$NF}' /etc/passwd

bin /sbin/nologin

daemon /sbin/nologin

adm /sbin/nologin

lp /sbin/nologin

mail /sbin/nologin

uucp /sbin/nologin



      4)、line ranges:行范围:

        startline,endine:/pat1/,/pat2/ 不支持直接给出数字格式:



[root@mysql-141 ~]# awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd

root

bin

daemon

adm

lp

nobody

[root@mysql-141 ~]# awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd

10 uucp

11 operator

12 games

13 gopher

14 ftp


  awk数组概念:

预备知识: 了解两种awk运算方法

    1) 累加运算 1+1+1

      i=i+1 i初始状态为0

      i++

      eg: 统计/etc/services文件中空行数量

      第一个里程: 找出文件中空行信息

      awk '/^$/' /etc/services


      第二个里程: 统计空行数量

      awk '/^$/{i=i+1;print i}' /etc/services


PS: awk中所有字符串信息都会识别为变量名称信息, 调取变量是不需要加上$符号

awk中想显示指定字符串信息, 需要在字符串外面加上双引号信息



[root@oldgirl ~]# awk '/^$/{i=i+1;print i}' /etc/services

1        #  i=i+1 i=0 i=0+1 --> i=1

2     #  i=i+1 i=1 i=1+1 --> i=2

3     #  i=2 i=2+1 --> i=3

4

5

6

7

8

9

10

11

12

13

14

15

16



[root@oldgirl ~]# awk '/^$/{i=i+1}END{print i}' /etc/services  # 将文件内容加载完之后,做出统计

16



    2) 求和运算 10+20+5

       i=i+$n i的初始状态为0   $n取第几列数值信息



[root@oldgirl ~]# seq 10|awk '{i=i+$0;print i}'

1 i=i+$0 i=0 $0=1 i=0+1 -- 1 1

2 i=i+$0 i=1 $0=2 i=1+2 -- 3 3

3 i=i+$0 i=3 $0=3 i=3+3 -- 6 6

4 10

5 15

6 21

7 28

8 36

9 45

10 55


  [root@mysql-141 ~]# seq 10|awk '{i=i+$0;print i}'

    1

    3

    6

    10

    15

    21

    28

    36

    45

    55



    3). 数组的表现形式        

        数组中的括号里面的内容


        hotel[元素01]=xiaolizi1  --- 调用print xiaolizi1[元素01]--- xiaolizi1

        hotel[元素02]=xiaolizi2 --- 调用print xiaolizi2[元素02]--- xiaolizi2


      数组统计命令组成说明:

      1) 找出要统计的信息

        $1


      2) 把指定要统计信息作为数组的元素

        h[$1]


      3) 利用统计运算公式,进行运算

        h[$1]=h[$1]+1 --- i=i+1


      4) 显示运算的结果信息

        a 只看某一个元素的结果信息


     awk '{h[$1]=h[$1]+1}END{print h["101.226.61.184"]}' access.log

     5

        b 要看全部元素的结果信息


     awk '{h[$1]=h[$1]+1}END{print h["101.226.61.184"],h["114.94.29.165"]}' access.log

# 精简后命令

      awk '{h[$1]++}END{for(name in h)print name,h[name]}' access.log




    for name in 101.226.61.184 114.94.29.165

      print h[$name]


      ==>

    for(name in h) --- > echo name=h=第一个元素信息

    echo name=h=第二个元素信息        


说明: 循环中读取数组名称==读取每一个元素名称信息



cat >>url.txt<<EOF

http://www.etiantian.org/index.html

http://www.etiantian.org/1.html

http://post.etiantian.org/index.html

http://mp3.etiantian.org/index.html

http://www.etiantian.org/3.html

http://post.etiantian.org/2.html

EOF

awk '{h[$1]++}END{for(name in h)print name,h[name]}' access.log


[root@mysql-141 ~]# awk '{h[$1]++}END{for(name in h)print name,h[name]}' access.log

101.226.61.184 5

27.154.190.158 2

218.79.64.76 2

114.94.29.165 1



第一步: 定义数组信息

awk '{h[$1]}' access.log

说明: 数组中的元素就是你关注要统计的列的信息


第二步: 进行统计运算,编写公式

awk '{h[$1]=h[$1]+1}' access.log


第三步: 编写元素循环信息

awk '{h[$1]=h[$1]+1}END{for(name in h)}' access.log


第四步: 输出结果信息   

awk '{h[$1]=h[$1]+1}END{for(name in h) print name,h[name]}' access.log

复制代码

 将文本内容格式化输出

  原文如下:


job_name    job_group

syncCommStockJob    dataSync

syncStoreChnlJob    dataSync

syncOrderJob    dataSync

syncReportStoreJob    dataSync

hdfsScanJob    report

orderSaleDailyJob    report

jdzmdOrdersJob    report

jdCanJob    report


  使用awk格式化输出后


cat xxx.txt | awk '{printf "%-30s%-15s\n",$1,$2}'              

      #%-30s表示输出字符串,宽度30位(字符串如果过长,可以自己调整),左对齐.%-15s用来指定第二列的,左对齐,宽度15.两个百分号之间可以没有空格.使用\n对每一行的输出加上换行符



job_name                      job_group     

syncCommStockJob              dataSync      

syncStoreChnlJob              dataSync      

syncOrderJob                  dataSync      

syncReportStoreJob            dataSync      

hdfsScanJob                   report                         

转自嘉为教育-rhce认证_rhce培训_linux培训_linux认证_linux考证

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容