awk高级命令
1.awk的介绍
-
awk是GNU的项目之一,是基于早期unix上的awk程序语言改善而来,所以现在我们在CentOS上用的awk其实是叫gawk。awk的作者这三个人:Aho,Kernighan,Weinberger,awk的命名方式是通过这三个人的名字的首字母而来。因为人们习惯用awk,所以后来干脆把awk创建了一个指向gawk的符号链接。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。 -
awk 编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输(stdin)、一个或多个文件,或其它命令的输出。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势 -
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理
2.awk的使用
语法:
awk [-F|-f|-v] ‘BEGIN{print "start"} /pattern/{command1; command2} END{print "end"}’ filename
- awk脚本通常由BEGIN语句+模式匹配+END语句三部分组成,这三部分都是可选项
- 其中 pattern 表示 AWK 在数据中查找的内容,而 commands 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来
- awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息
awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本
3.awk结构
- awk的基本操作是由输入行组成的序列中,陆续的扫描执行每一行,搜索可以被模式匹配的行,每一个输入行轮流被测试一遍,每匹配到一个模式,对应的动作就会执行,然后下一行开始,匹配重新开始,这个过程一直持续到文件被读取完毕为止。通常,模式是可选的,所以动作使用{}括起来,以便区分两者
- 命令行中的程序被单引号包围时,这个规定可以防止程序中的字符串(例如$)被shell解释,也可以让程序的的长度多于一行
- 当程序的长度比较短的时候,直接写会比较方便,但是比较长的时候,需要放到文件中,例如文件名为pgfile,这是只要键入awk -f pgfile 文本名
4.awk命令形式
awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
-F 指定输入行的分隔符,awk 命令默认分隔符为空格或制表符 -f 从脚本文件中读取 awk 脚本指令,以取代直接在命令行中输入指令 -v var=val 在执行处理过程之前,设置一个变量 var,并给其设备初始值为 val ’ ’ 引用代码块 // 匹配代码块,可以是字符串或正则表达式 {} 命令代码块,包含一条或多条命令 ; 多条命令使用分号分隔 BEGIN 在 awk 程序一开始,未读取任何数据之前执行。BEGIN 后的动作只在程序开始时执行一次 END 在 awk 程序处理完所有数据,即将结束时执行?END 后的动作只在程序结束时执行一次
注意
- BEGIN 主要是初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
- END 主要是结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息
5.akw内置变量
$0 表示整个当前行 $1 ~ $n 当前记录的第N个字段 FS 输入字段分隔符(-F相同作用)默认空格 RS 输入记录分割符,默认换行符(即文本是按一行一行输入) NF 字段个数就是列 NR 记录数,就是行号,默认从1开始 FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始 OFS 输出字段分隔符,默认空格 ORS 输出记录分割符,默认换行符 \t 制表符 \n 换行符 ~ 匹配,与==相比不是精确比较 !~ 不匹配,不精确比较 == 等于,必须全部相等,精确比较 != 不等于,精确比较 && 逻辑与
6.匹配模式
当awk读入一行是时,它试图匹配脚本中的每个模式匹配规则。只有与一个特定的模式相匹配的输入行才能成为操作对象。如果没有指定操作,于模式相匹配的输入行将被打印出来
[root@shen ~]# cat tests
This line of data is ingored
//空行
//空行
[root@shen ~]# awk '/^$/{print "This is a blank line."}' test
This is a blank line.
This is a blank line.
[root@node2 ~]# awk '/data/' test
This line of data is ingored
7.记录和字段
awk将每个输入行作为一条记录,而将由空格或制表符分隔的单词(即列)作为字段((用来分隔字段的字符被称为分隔符)。
[root@shen ~]# echo 'shen long fei'|awk '{print $3}' //打印第三个字段
fei
[root@shen ~]# echo 'shen long fei'|awk 'BEGIN{one=1;tow=2}{print $(one + tow)}' //定义变量打印$3
fei
在这里打印 IP地址
[root@shen ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:e7:1d:29 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.147/24 brd 192.168.100.255 scope global dynamic noprefixroute ens33
valid_lft 1270sec preferred_lft 1270sec
inet6 fe80::79b2:48d0:db63:ff3e/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@lshen ~]# ip a|grep 'inet '|grep -v '127.0.0.1'|awk -F '[ /]+' '{print $3}'
192.168.100.147
[root@localhost ~]#
编写匹配规则,打印特定的字段
[root@shen ~]# cat tests
This line of shen is ingored
This line of long is ingored
This line of fei is ingored
[root@shen ~]# awk '/long/{print $1 $6}' tests
Thisingored
[root@shen ~]# awk '/long/{print $1","$6}' test //指定','作为域分隔符
This,ingored
[root@shen ~]# awk '/long/{print $1", "$6}' test //指定‘, ’作为域分隔符
This, ingored
匹配指定一列的字段,并且打印
[root@shen ~]# cat tests
This line of shen is ingored
This line of long is ingored
This line of fei is ingored
This line of is long sb
[root@shen ~]# awk '/long/{print $1","$6}' tests //未指定匹配那一例
This,ingored
This,sb
[root@shen ~]# awk '$4 ~/long/{print $1" "$6}' tests
This ingored
使用(!~)来反转规则的意思,即第四列这个字段不包含long的打印出来
[root@shen ~]# awk '$4 !~/tom/{print $1" "$6}' tests
This ingored
This ingored
This sb
8.字段的划分
akw有三种分割字段的方法
- 第一个方法是用空白字符来分隔字段。将FS设置为一个空格。在这种情况下,记录的前导空白字符和结尾空白字符(空格和/或制表符)将被忽略。并且字段空格和/或制表位来分隔。因为FS的默认值为一个空格,所以这也是通常情况下awk将记录划分为字段的方法。
- 第二个方法是使用其他单个字符来分隔字段。例如,awk程序经常使用“:”作为分隔符。当FS表示任何单个字符时,在这个字符出现的任何地方都将分隔出另外一个字段。如果出现两个连续的分隔符,在它们之间的字段值为空串。
- 方法是,如果你设置了不止一个字符作为字段分隔符,它将被作为一个正则表达式来解释。
[root@shen ~]# cat passwd
root:x:0:0 root:/root:/bin/bash
bin:x:1:1 bin:/bin:/sbin/nologin
[root@shen ~]# awk '{print $2}' passwd
root:/root:/bin/bash
bin:/bin:/sbin/nologin
[root@shen ~]# awk 'BEGIN{FS=":"}{print $3}' passwd
0
1
awk 中有许多系统变量或内置变量。awk有两种类型的系统变量。第一种类型定义的变量默认值可以改变,例如默认的字段和记录分隔符。第二种类型定义的变量的值可用于报告或数据处理中。例如当前记录中字段的数量,当前记录的数量等。这些可以由 awk自动更新,例如,当前记录的编号和输入文件名。
9.OFS输出字段分隔符
OFS和FS等效的输出分隔符,他的默认值是空格
[root@shen ~]# cat passwd
root:x:0:0 root:/root:/bin/bash
bin:x:1:1 bin:/bin:/sbin/nologin
[root@shen ~]# awk 'BEGIN{FS=":"}{print $1,$6}' passwd
root /bin/bash
bin /sbin/nologin
[root@shen ~]# awk 'BEGIN{FS=":";OFS="-"}{print $1,$6}' passwd
root-/bin/bash
bin-/sbin/nologin
10.NF
NF变量定义为当前输入记录的字段个数,也就是有几列。
[root@shen ~]# cat tests
shen 82 93 48 94 88
long 81 96 75 99 86 93
fei 82 88 80 93 81 94 89
[root@shen ~]# awk '{print NF}' tests
6
7
8
[root@shen ~]# awk '{print $NF}' tests
88
93
89
11.NR行号
NR是每行的行号,多文件记录递增。
[root@shen ~]# cat tests
shen 82 93 48 94 88
long 81 96 75 99 86 93
fei 82 88 80 93 81 94 89
[root@shen ~]# awk '{print NR $1}' tests
1shen
2long
3fei
[root@shen ~]# awk '{print NR $1}' tests
1.shen
2.long
3.fei
[root@shen ~]# awk '{print NR "." $0}' tests
1.shen 82 93 48 94 88
2.long 81 96 75 99 86 93
3.fei 82 88 80 93 81 94 89
12.RS
处理这种包括多行数据的记录,我们可以将字段分隔符定义为换行符,换行符用“\n”来表示,并将记录分隔符设置为空字符串,它代表一个空行。
[root@shen ~]# cat tests
shen 82 93 48 94 88
long 81 96 75 99 86 93
fei 82 88 80 93 81 94 89
[root@shen ~]# awk 'BEGIN{FS="\n";RS=""}{print $1}' run
shen 82 93 48 94 88
[root@shen ~]# awk 'BEGIN{FS="\n";RS=""}{print $3}' run
fei 82 88 80 93 81 94 89
|