文本处理三剑客之awk

前言

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

简要介绍文本处理三工具:
grep, sed, awk
grep, egrep, fgrep:文本过滤工具;pattern
sed:行编辑器,模式空间、保持空间
awk:报告生成器,格式化文本输出


awk介绍

awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出
有多种版本:New awk(nawk),GNU awk( gawk)
gawk:模式扫描和处理语言

awk格式
基本用法: 
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语句块

3部分组成 program通常是被单引号或双引号

awk选项

基础选项:

    -F 指明输入时用到的字段分隔符 
    -v var=value: 自定义变量


awk基本结构
pattern和action: 
        • pattern部分决定动作语句何时触发及触发事件 BEGIN,END 
        • action statements对数据进行处理,放在{}内指明 print,printf 分割符、域和记录 
        • awk执行时,由分隔符分隔的字段(域)标记$1,$2..$n称 为域标识。$0为所有域,注意:和shell中变量$符含义不同 
        • 文件的每一行称为记录 
        • 省略action,则默认执行 print $0 的操作
awk工作原理

第一步:执行BEGIN{action;… }语句块中的语句

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,
从第一行到最后一行重复这 个过程,直到文件全部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;…}语句块

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

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

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

awk基础用法

print格式:print item1, item2, …
要点:

    • (1) 逗号分隔符 
    • (2) 输出的各item可以字符串,也可以是数值;当前记录的字段、 变量或awk的表达式 
    • (3) 如省略item,相当于print $0 

国际惯栗(举个栗子):

栗子1.
栗子解释:
awk 语句后面没有选择要处理的文本,则等待用户输入再来作出回应。

[ root@ygl ~ ]# awk '{print "hello,awk"}'
ni hao  <--输入ni hao 就会打印hello,awk
hello,awk

栗子2.
栗子解释:
-F后面跟的指明输入时用到的字段分隔符
因为没有选择输出的item相当于print $0

[ root@ygl ~ ]# awk -F: '{print}' /etc/passwd 
root:x:0:0:root,,62985600:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
....

栗子3.
栗子解释:
print 后面跟的是”wang”则每处理一行文本就会打印一次wang

[ root@ygl ~ ]# awk -F: '{print "wang"}' /etc/passwd
wang
wang
wang
wang
...

栗子4.
栗子解释:
以:为分隔符为输入字段的分割符,然后打印以:为分隔符的第一列文本。

[ root@ygl ~ ]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
...

栗子5.
栗子解释:
以:为输入分割符,打印第一列再横向跳到下一个制表符的位置再打印第三列

[ root@ygl ~ ]# awk -F: '{print $1"\t"$3}' /etc/passwd
root    0
bin     1
daemon  2
adm     3
lp      4
sync    5
...

栗子6.
栗子解释:
首先提取/etc/fstab文件的最后三行,再通过管道传给awk处理工具,
用awk工具打印第二和第四行。

[ root@ygl ~ ]# tail -3 /etc/fstab |awk '{print $2,$4}'
/boot defaults
swap defaults
/media/cdrom defaults

awk变量

awk内置变量
  • FS:输入字段分隔符,默认为空白字符
    对比栗子: 注意:通过对比可以清晰的看到打印出来的两列中间多了我们定义的输入字段分隔符
[ root@ygl ~ ]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
[ root@ygl ~ ]# awk -v FS=':' '{print $1,FS,$3}' /etc/passwd 
root : 0
bin : 1
daemon : 2
adm : 3
lp : 4
sync : 5
shutdown : 6
  • OFS:输出字段分隔符,默认为空白字符
    栗子:
[ root@ygl ~ ]# awk -v FS=':' -v OFS='-' '{print $1,$3,$7}' /etc/passwd
root-0-/bin/bash
bin-1-/sbin/nologin
daemon-2-/sbin/nologin
adm-3-/sbin/nologin
lp-4-/sbin/nologin
sync-5-/bin/sync
shutdown-6-/sbin/shutdown
  • RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效
    栗子:
[ root@ygl ~ ]# awk -v RS=' ' '{print }' /etc/passwd
root:x:0:0:root,,62985600:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
  • ORS:输出记录分隔符,输出时用指定符号代替换行符
    栗子:
[ root@ygl ~ ]# awk -v RS=' ' -v ORS='###' '{print}' /etc/passwd
...
ftp:x:14:50:FTP###User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-bus-proxy:x:999:998:systemd###Bus###Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd###Network###Management:/:/sbin/nologin
dbus:x:81:81:System###message###bus:/:/sbin/nologin
  • NF:字段数量
    注意:引用内置变量不用 就相当于打印了第$NF个字段)

栗子1:

 [ root@ygl ~ ]# awk -F: '{print NF}' /etc/fstab
0
1
1
3
1
1

栗子2:

[ root@ygl ~ ]# awk -F: '{print $(NF-1)}' /etc/passwd
/root
/bin
/sbin
/var/adm
/var/spool/lpd
/sbin
/sbin
/sbin
  • NR:行号
    对比栗子:
[ root@ygl ~ ]# awk '{print NR}' /etc/fstab 
1
2
3
4
5
6
7
8
9
10
11
12
13
[ root@ygl ~ ]# awk END'{print NR}' /etc/fstab
13
  • FNR:各文件分别计数,行号
    栗子:
    注意:FNR变量对各文件的行数是分别记数的
    [ root@ygl ~ ]# awk '{print FNR}' /etc/fstab /etc/inittab
    1
    2
    3
    4
    5
    1
    2
    3
    4
    5
    6


  • FILENAME:显示当前文件名

栗子:
    [ root@ygl ~ ]# awk '{print FILENAME}' /etc/fstab 
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab


  • ARGC:命令行参数的个数

栗子:
注意:(第一个是awk第二个是/etc/fstab第三个是/etcinittab)
    [ root@ygl ~ ]# awk '{print ARGC}' /etc/fstab /etc/inittab
    3
    3
    3
    3
    3
    3
    [ root@ygl ~ ]# awk 'BEGIN {print ARGC}' /etc/fstab /etc/inittab
    3


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

栗子:
注意:(第一个元素是awk第二个是/etc/fstab第三个是/etc/inittab)
    [ root@ygl ~ ]# awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab
    awk
    [ root@ygl ~ ]# awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab
    /etc/fstab
    [ root@ygl ~ ]# awk 'BEGIN {print ARGV[2]}' /etc/fstab /etc/inittab
    /etc/inittab
awk自定义变量
自定义变量(区分字符大小写)
    (1) -v var=value
    (2) 在program中直接定义

国际惯栗:

栗子1:

    [ root@ygl ~ ]# awk -v test='hello gawk' '{print test}' /etc/fstab
    hello gawk
    hello gawk
    hello gawk
    hello gawk
    hello gawk
    hello gawk
    [ root@ygl ~ ]# awk -v test='hello gawk' 'BEGIN{print test}'
    hello gawk
    [ root@ygl ~ ]# awk 'BEGIN{test="hello,gawk";print test}'
    hello,gawk

栗子2:

    [ root@ygl ~ ]# awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
    root male 
    bin male 18
    daemon male 18
    adm male 18
    lp male 18
    sync male 18

注意:仔细观看!!!上面的栗子是再打印了一次$1、sex、age以后才定义的age=18
第一次因为age没有值所以没有输出。而下面则是则是在开始就定义了age=18。

    [ root@ygl ~ ]# awk -F: '{sex="male";age=18;print $1,sex,age}' /etc/passwd
    root male 18
    bin male 18
    daemon male 18
    adm male 18
    lp male 18
    sync male 18
    shutdown male 18

栗子3
简单的讲解基本的调用awk脚本的方法

    [ root@ygl ~ ]# cat awkscript 
    {print script,$1,$2}
    [ root@ygl ~ ]# awk -F: -f awkscript script="awk" /etc/passwd
    awk root x
    awk bin x
    awk daemon x
    awk adm x
    awk lp x
    awk sync x
    awk shutdown x
    awk halt x


awk之printf命令

printf命令
格式化输出:printf “FORMAT”, item1, item2, ... 
    (1) 必须指定FORMAT 
    (2) 不会自动换行,需要显式给出换行控制符,\n 
    (3) FORMAT中需要分别为后面每个item指定一个格式化符号 
格式符:与item一一对应
    %c: 显示字符的ASCII码 
    %d, %i: 显示十进制整数 
    %e, %E:显示科学计数法数值 
    %f:显示为浮点数 
    %g, %G:以科学计数法或浮点形式显示数值 
    %s:显示字符串 
    %u:无符号整数
    %%: 显示%自身   
修饰符:
    #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f 
    -: 左对齐(默认右对齐) %-15s 
    +:显示数值的正负符号 %+d
国际惯栗:

栗子1:

[ root@ygl ~ ]# awk -F: '{printf "%s",$1}' /etc/passwd
rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemdbusproxysystemdnetworkdbuspolkitdabrtunboundtsslibstoragemgmtrpccolordusbmuxdsaslauthgeocluertkitradvdrpcusernfsnobodyqemuchronysetroubleshootpulsegdmgnomeinitialsetupsshdavahipostfixntptcpdumpyglapachequagga

栗子2:

    [ root@ygl ~ ]# awk -F: '{printf "%s\n",$1}' /etc/passwd
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    mail

栗子3:

[ root@ygl ~ ]# awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
root                          0
bin                           1
daemon                        2
adm                           3
lp                            4
sync                          5
shutdown                      6
halt                          7

栗子4:

[ root@ygl ~ ]# awk -F: '{printf "Username: %s\n",$1}' /etc/passwd
Username: root
Username: bin
Username: daemon
Username: adm
Username: lp
Username: sync
Username: shutdown

栗子5:

[ root@ygl ~ ]# awk -F: '{printf "Username: %s,UID:%d\n",$1,$3}' /etc/passwd
Username: root,UID:0
Username: bin,UID:1
Username: daemon,UID:2
Username: adm,UID:3
Username: lp,UID:4
Username: sync,UID:5
Username: shutdown,UID:6

栗子6:

[ root@ygl ~ ]# awk -F: '{printf "Username: %15s,UID:%d\n",$1,$3}' /etc/passwd
Username:            root,UID:0
Username:             bin,UID:1
Username:          daemon,UID:2
Username:             adm,UID:3
Username:              lp,UID:4
Username:            sync,UID:5
Username:        shutdown,UID:6

栗子7:

[ root@ygl ~ ]# awk -F: '{printf "Username: %-15sUID:%d\n",$1,$3}' /etc/passwd
Username: root           UID:0
Username: bin            UID:1
Username: daemon         UID:2
Username: adm            UID:3
Username: lp             UID:4
Username: sync           UID:5
Username: shutdown       UID:6

awk操作符

算术操作符
    算术操作符: 
        x+y, x-y, x*y, x/y, x^y, x%y 
            -x: 转换为负数 
            +x: 转换为数值
字符串操作符
    没有符号的操作符
    字符串连接
赋值操作符
    =, +=, -=, *=, /=, %=, ^= 
    ++, -- 
比较操作符
    ==, !=, >, >=, <= 
模式匹配符
    ~:左侧的字符串是否能被右侧的模式所匹配
    !~:是否不匹配 
逻辑操作符
    与&&
    或||
    非!
条件表达式(三目表达式)*
    selector?if-true-expression:if-false-expression 
awk PATTERN
PATTERN:根据pattern条件,过滤匹配的行,再做处理 
    (1)如果未指定:空模式,匹配每一行 
    (2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来 awk '/^UUID/{print $1}' /etc/fstab awk '!/^UUID/{print $1}' /etc/fstab 
    (3) relational expression: 关系表达式,结果为“真”才会被处理 真:结果为非0值,非空字符串 假:结果为空字符串或0值 
    (4) line ranges:行范围 
    startline,endline:/pat1/,/pat2/ 不支持直接给出数字 格式 
    (5) BEGIN/END模式 
    BEGIN{}: 仅在开始处理文件中的文本之前执行一次 
    END{}:仅在文本处理完成之后执行一次
国际惯栗

算术栗子:

[ root@ygl ~ ]# awk 'BEGIN{print 1+2}'
3

模式栗子1:

[ root@ygl ~ ]# awk -F: '$0 ~ /root/{print $1}' /etc/passwd
root
operator

模式栗子2:

[ root@ygl ~ ]# awk '$0~"^root"' /etc/passwd
root:x:0:0:root,,62985600:/root:/bin/bash

模式栗子3:

[ root@ygl ~ ]# awk '$0 !~ /root/' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
...

比较栗子:

[ root@ygl ~ ]# awk -F: '$3==0' /etc/passwd
root:x:0:0:root,,62985600:/root:/bin/bash

比较和逻辑栗子:

[ root@ygl ~ ]# awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown

比较和逻辑栗子:

[ root@ygl ~ ]# awk -F: '!($3>=500) {print $3}' /etc/passwd
0
1
2
3
4
5

比较和逻辑栗子:

[ root@ygl ~ ]# awk -F: '!($3==0) {print $1}' /etc/passwd
bin
daemon
adm
lp
sync
shutdown

三目表达式栗子:
注意:这是三目表达式的栗子,很重要!!!

[ root@ygl ~ ]# awk -F: '{$3>=1000?usertype="CommonUser":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
           root:Sysadmin or SysUser
            bin:Sysadmin or SysUser
         daemon:Sysadmin or SysUser
            adm:Sysadmin or SysUser
             lp:Sysadmin or SysUser
           sync:Sysadmin or SysUser
       shutdown:Sysadmin or SysUser

PATTERN栗子:

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

PATTERN栗子:
注意:匹配第一列以root开头到第一列以nobody开头的行,打印之。

[ root@ygl ~ ]# awk -F: '/^root\>/,/^nobody\>/{print $0}' /etc/passwd
root:x:0:0:root,,62985600:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin

综合栗子:
注意:匹配10到20行并打印行号和第一列。

[ root@ygl ~ ]# awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
10 operator
11 games
12 ftp
13 nobody
14 systemd-bus-proxy
15 systemd-network
16 dbus
17 polkitd
18 abrt
19 unbound
20 tss

综合栗子:
注意:首先打印前两行:
USER UID
—————

然后在做判断匹配10到15行,
打印第一和第三列。
最后结束时在打印

==============

[ root@ygl ~ ]# awk -F: 'BEGIN{print " USER UID \n--------------- "}(NR>=10&&NR<=15){print $1,$3}END{print "=============="}' /etc/passwd
 USER UID 
--------------- 
operator 11
games 12
ftp 14
nobody 99
systemd-bus-proxy 999
systemd-network 192
==============

awk action

awk action

    常用的action分类 
            • (1) Expressions:算术,比较表达式等 
            • (2) Control statements:if, while等 
            • (3) Compound statements:组合语句 
            • (4) input statements 
            • (5) output statements:print
awk控制语句if-else
awk控制语句if-else 
    语法:
        if(condition){statement;…}[else statement] 
        if(condition1){statement1}else if(condition2){statement2} else{statement3} 

使用场景:对awk取得的整行或某个字段做条件判断

举几个栗子:

[ root@ygl ~ ]# awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
nfsnobody 65534
ygl 1000
[ root@ygl ~ ]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
root
ygl

打印/etc/fstab列数大于5的行

[ root@ygl ~ ]# awk '{if(NF>5) print $0}' /etc/fstab
# Created by anaconda on Fri Jul 14 11:15:46 2017
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
UUID=948da9df-62e8-4550-a391-95348ee5018b /                   xfs     defaults        0 0
UUID=4c8420c9-b930-4688-91ab-dc1cfbc0b7e1 /app                xfs     defaults        0 0
UUID=80e3fa3a-fc81-478a-bef3-d322ea65c799 /boot               xfs     defaults        0 0
UUID=0df71ca6-ef01-4ecf-a436-0be749ad781d swap                swap    defaults        0 0
UUID=2016-12-05-13-52-39-00      /media/cdrom        iso9660  defaults        0 0

注意:为了方便观察我加了条件行号大于40的
条件判断首先要行号大于40,然后在条件判断第三列是否大于等于1000,
如果大于等于就打印Common user:第一列
如果小就打印root or Sysuser:第一列

[ root@ygl ~ ]# awk -F: '(NR>=40){if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
root or Sysuser: ntp
root or Sysuser: tcpdump
Common user: ygl
root or Sysuser: apache
root or Sysuser: quagga

注意:清晰理解awk中的if-else if-else的栗子!!!

[ root@ygl ~ ]# awk 'BEGIN{ test=100;if(test>90){print "very good"} else if(test>60){print "good"}else{print "no pass"}}'
very good
awk控制语句while循环
while循环 
    语法:while(condition){statement;…} 
        条件“真”,进入循环;条件“假”,退出循环 
    使用场景: 
        对一行内的多个字段逐一类似处理时使用 
        对数组中的各元素逐一处理时使用 

举几个栗子
注意:匹配/etc/grub2.cfg里面以空白字符开头行中有linux16的行
再对i赋值等于1进入while循环
当i小于等于总列数时打印第i列并通过函数length()统计这列的字符数
最后i自加1再次进入while循环

[ root@ygl ~ ]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=948da9df-62e8-4550-a391-95348ee5018b 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-7f1277af09f84cbf812764ec7381da55 50
root=UUID=948da9df-62e8-4550-a391-95348ee5018b 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5

和上面一样先进入while循环,但是这里嵌套了一个if语句再次判断,
进入if判断语句,当这一列的字符数大于等于10时才打印第i列和这列字符数再i自加1
再回到while语句判断

[ root@ygl ~ ]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=948da9df-62e8-4550-a391-95348ee5018b 46
crashkernel=auto 16
LANG=en_US.UTF-8 16
/vmlinuz-0-rescue-7f1277af09f84cbf812764ec7381da55 50
root=UUID=948da9df-62e8-4550-a391-95348ee5018b 46
crashkernel=auto 16
awk控制语句do-while循环
do-while循环 
    语法:do {statement;…}while(condition) 
    意义:无论真假,至少执行一次循环体

举个栗子

[ root@ygl ~ ]# awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}'
5050
awk控制语句for循环
for循环 
    语法:
        for(expr1;expr2;expr3) {statement;…} 
    常见用法:
        for(variable assignment;condition;iteration process) {for-body} 
    特殊用法:能够遍历数组中的元素 
    语法:
        for(var in array) {for-body} 

举个栗子
和上面的while循环差不多就不过多讲解了…

[ root@ygl ~ ]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=948da9df-62e8-4550-a391-95348ee5018b 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-7f1277af09f84cbf812764ec7381da55 50
root=UUID=948da9df-62e8-4550-a391-95348ee5018b 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
awk特殊控制语句
switch语句 
break语句
continue语句
next语句

简单的举几个栗子

[ root@ygl ~ ]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++) {if(i%2==0)continue;sum+=i}print sum}'
2500
[ root@ygl ~ ]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++) {if(i==66)break;sum+=i}print sum}'
2145

这个栗子是匹配第三列是双数的行,打印第一列和第三列。

[ root@ygl ~ ]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
root 0
daemon 2
lp 4
shutdown 6
mail 8
games 12
ftp 14
systemd-network 192
polkitd 998
...

awk数组

关联数组
关联数组:array[index-expression] 
index-expression: 
    • (1) 可使用任意字符串;字符串要使用双引号括起来 
    • (2) 如果某数组元素事先不存在,在引用时,awk会自动创建 此元素,并将其值初始化为“空串” 
    • (3) 若要判断数组中是否存在某元素,要使用“index in array”格 式进行遍历 

举几个栗子

[root@ygl~]#weekdays["mon"]="Monday";awk'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
Tuesday
Monday

首先要判断第7列是不是空的,不是就把这个字符串看成一个变量自加1,
再打印第七列和这个字符串变量
(就是看这个字符串出现了几次了)

[ root@ygl ~ ]# awk -F: '{!arr[$7]++}{print $7,arr[$7]}'  /etc/passwd
/bin/bash 1
/sbin/nologin 1
/sbin/nologin 2
/sbin/nologin 3
/sbin/nologin 4
/bin/sync 1
/sbin/shutdown 1
/sbin/halt 1
/sbin/nologin 5
遍历数组
若要遍历数组中的每个元素,要使用for循环 
    for(var in array) {for-body} 
注意:var会遍历array的每个索引 

举几个栗子
这种写法可以更清楚的学习awk数组…

[ root@ygl ~ ]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
Tuesday
Monday

轻松观察有几个监听有几个在连接..

[ root@ygl ~ ]# netstat -tan | awk '/^tcp/{state[$NF]++}END {for(i in state) { print i,state[i]}}'
LISTEN 10
ESTABLISHED 1

最后送上代码一条,观察有哪些ip访问过访问了多少次你的机器,那些疯狂访问的…

awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log

最后

awk语句真的很强大,精简,且循环运行速度比bash脚本的循环强上太多太多了,
写起来逻辑十分简单,就是语法实在是太多变了….




ღ ღ ღ 如果觉得文章对您有用,不妨赞一下ღ ღ ღ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值