Linux 三剑客命令之 awk 详解

目录

一、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 对输入文件中的每一行都执行这个脚本。

Linux 三剑客命令之 awk 详解_第1张图片

$ 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 运算符

Linux 三剑客命令之 awk 详解_第2张图片

  • 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 内置变量

Linux 三剑客命令之 awk 详解_第3张图片

  • 字段分隔符 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  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
        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 正则

Linux 三剑客命令之 awk 详解_第4张图片

  • 规则表达式

        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 常用字符串函数

Linux 三剑客命令之 awk 详解_第5张图片

Linux 三剑客命令之 awk 详解_第6张图片

  • 替换

        在 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

你可能感兴趣的:(Shell,linux,unix,服务器)