目录

一、Awk 实战讲解

1.1 awk 的原理

1.2 BEGIN 和 END 模块

1.3 运算符

1.4 常用 awk 内置变量

1.5 awk 正则

1.6 awk 常用字符串函数


一、Awk 实战讲解

        awk 是一种很棒的语言,它适合文本处理和报表生成,其语法较为常见,借鉴了某些语言的一些精华,如 C 语言等。在 linux 系统日常处理工作中,发挥很重要的作用,掌握了 awk 将会使你的工作变的高大上。 awk 是三剑客的老大,利剑出鞘,必会不同凡响。

1.1 awk 的原理

通过一个简短的命令,我们来了解其工作原理:

$ awk '{print $0}' /etc/passwd
$ echo hhh | awk '{print "hello,world"}'
$ awk '{ print "hiya" }' /etc/passwd

        你将会见到 /etc/passwd 文件的内容出现在眼前。现在,解释 awk 做了些什么。调用 awk时,我们指定 /etc/passwd 作为输入文件。执行 awk 时,它依次对 /etc/passwd 中的每一行执行 print 命令。所有输出都发送到 stdout,所得到的结果与执行 cat /etc/passwd 完全相同。

        现在,解释 { print } 代码块。在 awk 中,花括号用于将几块代码组合到一起,这一点类似于 C 语言。在代码块中只有一条 print 命令。在 awk 中,如果只出现 print 命令,那么将打印当前行的全部内容。

再次说明,awk 对输入文件中的每一行都执行这个脚本。

$ awk -F":" '{ print $1 }' /etc/passwd
$ awk -F":" '{ print $1 $3 }' /etc/passwd
$ awk -F":" '{ print $1 " " $3 }' /etc/passwd
$ awk -F":" '{ print "username: " $1 "\t\tuid:" $3" }' /etc/passwd

1.2 BEGIN 和 END 模块

        通常,对于每个输入行,awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,
可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况,awk 允许
您定义一个 BEGIN 块。我们在前一个示例中使用了 BEGIN 块。因为 awk 在开始处理输入文
件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它
在程序中以后会引用的全局变量的极佳位置。

        awk 还提供了另一个特殊块,叫作 END 块。awk 在处理了输入文件中的所有行之后执行
这个块。通常,END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

1.3 运算符

  • awk 赋值运算符

a+5;等价于: a=a+5; 其他同类

[root@master1-admin ~]# awk 'BEGIN{a=5;a+=5;print a}'
10
  • awk 逻辑运算符
[root@master1-admin ~]# awk 'BEGIN{a=1;b=2;print(a>2&&b>1,a=1||b>1)}'
0 1
  • awk 正则运算符 
[root@master1-admin ~]# awk 'BEGIN{a="100testaaa";if(a~/100/){print "ok"}}'
ok

[root@master1-admin ~]# echo | awk 'BEGIN{a="100testaaa"}a~/100/{print "ok"}'
ok
  • 关系运算符

        如:> < 可以作为字符串比较,也可以用作数值比较,关键看操作数如果是字符串就会转换为字符串比较。两个都为数字才转为数值比较。字符串比较:按照 ascii 码顺序比较。 

[root@master1-admin ~]# awk 'BEGIN{a="11";if(a>=9){print "ok"}}'
[root@master1-admin ~]# awk 'BEGIN{a=11;if(a>=9){print "ok"}}'
ok
[root@master1-admin ~]# awk 'BEGIN{a;if(a>=b){print "ok"}}'
ok
  • awk 算术运算符

说明,所有用作算术运算符进行操作,操作数自动转为数值,所有非数值都变为 0。

[root@master1-admin ~]# awk 'BEGIN{a="b";print a++,++a}'
0 2

[root@master1-admin ~]# awk 'BEGIN{a="20b4";print a++,++a}'
20 22

1.4 常用 awk 内置变量

  • 字段分隔符 FS

FS="\t" 一个或多个 Tab 分隔

[root@master1-admin ~]# vim tab.txt
ww	CC	IDD

[root@master1-admin ~]# awk 'BEGIN{FS="\t+"}{print $1,$2,$3}' tab.txt
ww CC IDD 

FS="[[:space:]+]" 一个或多个空白空格,默认的

[root@master1-admin ~]# vim space.txt
we are    studing awk now!

[root@master1-admin ~]# awk -F [[:space:]+] '{print $1,$2,$3,$4,$5}' space.txt
we are 

[root@master1-admin ~]# awk -F [[:space:]+] '{print $1,$2}' space.txt
we are

FS="[" ":]+" 以一个或多个空格或:分隔

[root@master1-admin ~]# vim hello.txt
root:x:0:0:root: /root:/bin/bash

[root@master1-admin ~]# awk -F [" ":]+ '{print $1,$2,$3}' hello.txt
root x 0
  • 字段数量 NF

[root@master1-admin ~]# vim hello.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin:888

[root@master1-admin ~]# awk -F ":" 'NF==8{print $0}' hello.txt
bin:x:1:1:bin:/bin:/sbin/nologin:888
  • 记录数量 NR
[root@master1-admin ~]# ifconfig ens32
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.78.135  netmask 255.255.255.0  broadcast 192.168.78.255
        inet6 fe80::20c:29ff:fe2e:bef7  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:2e:be:f7  txqueuelen 1000  (Ethernet)
        RX packets 3553  bytes 295498 (288.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13802  bytes 1002340 (978.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@master1-admin ~]# ifconfig ens32 | awk -F [" ":]+ 'NR==2{print $3}'
192.168.78.135
  • RS 记录分隔符变量

        将 FS 设置成 "\n" 告诉 awk 每个字段都占据一行。通过将 RS 设置成 "",还会告诉 awk
每个地址记录都由空白行分隔。 

[root@master1-admin ~]# vim recode.txt
Jimmy the Weasel
100 Pleasant Drive
San Francisco, CA 12345

Big Tony
200 Incognito Ave.
Suburbia, WA 67890

[root@master1-admin ~]# vim awk.txt
#!/bin/awk
BEGIN {
    FS="\n"
    RS=""
}
{
    print $1 ", " $2 ", " $3
}

[root@master1-admin ~]# awk -f awk.txt recode.txt
Jimmy the Weasel, 100 Pleasant Drive, San Francisco, CA 12345
Big Tony, 200 Incognito Ave., Suburbia, WA 67890
  • OFS 输出字段分隔符

[root@master1-admin ~]# awk 'BEGIN{FS=":"}{print $1","$2","$3}' hello.txt
root,x,0
bin,x,1
[root@master1-admin ~]# awk 'BEGIN{FS=":";OFS="#"}{print $1,$2,$3}' hello.txt
root#x#0
bin#x#1
  •  ORS 输出记录分隔符

[root@master1-admin ~]# vim awk.txt
#!/bin/awk
BEGIN {
    FS="\n"
    RS=""
    ORS="\n\n"
}
{
    print $1 ", " $2 ", " $3
}

[root@master1-admin ~]# awk -f awk.txt recode.txt
Jimmy the Weasel, 100 Pleasant Drive, San Francisco, CA 12345

Big Tony, 200 Incognito Ave., Suburbia, WA 67890

1.5 awk 正则

  • 规则表达式

        awk '/REG/{action} ' file,/REG/ 为正则表达式,可以将 $0 中,满足条件的记录送入到:
action 进行处理 

[root@master1-admin ~]# awk '/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@master1-admin ~]# awk -F : '$5~/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

# 取出 ip
[root@master1-admin ~]# ifconfig ens32 | awk 'BEGIN{FS="[[:space:]:]+"} NR==2{print $3}'
192.168.78.135
  • 布尔表达式

awk '布尔表达式{action}' file 仅当对前面的布尔表达式求值为真时,awk 才执行代码块。

[root@master1-admin ~]# awk -F: '$1=="root"{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

[root@master1-admin ~]# awk -F: '($1=="root")&&($5=="root"){print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

1.6 awk 常用字符串函数

  • 替换

        在 info 中查找满足正则表达式,/[0-9]+/ 用 ”!” 替换,并且替换后的值,赋值给 info 未给 info 值,默认是 $0 

[root@master1-admin ~]# awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'
this is a test!test!
  • 查找
# 未找到,返回 0
[root@master1-admin ~]# awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}'
ok
  • 匹配查找 

如果查找到数字则匹配成功返回 ok,否则失败,返回未找到 

[root@master1-admin ~]# awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}'
ok
  • 截取
# 从第 4 个 字符开始,截取 10 个长度字符串
[root@master1-admin ~]# awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}'
s is a tes
  • 分割
# 分割 info,动态创建数组 tA,awk for ...in 循环,是一个无序的循环。并不是从数组下标 1...n 开始
[root@master1-admin ~]# awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}'
4
4 test
1 this
2 is
3 a

Logo

更多推荐