awk命令

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了awk命令相关的知识,希望对你有一定的参考价值。

1.awk命令

awk的设计使得他非常适合处理由行列组成的文本数据。awk还是一种编程语言环境,他提供了正则表达式的匹配,流程控制,运算符,表达式,变量,以及函数等一系列的程序设计语言所具备的特性。



2.awk命令的基本语法

awk命令的基本语法:

awk  匹配模式  { 执行的操作 }



2.1 awk的工作流程

awk处理数据时,他会反复执行一下4个步骤:

1.自动的从数据文件中读取文本的行。

2.自动更新 awk 的内置系统变量的值。例如:列数变量NF,行数变量NR,行变量$0,各个变量$1,$2等。

3.依次执行程序中的所有的匹配模式及其操作。

4.当执行完程序的所有匹配模式和操作后,如果数据文件中仍有未读取的数据行,则返回第一步重复执行1~4的操作。



2.2 awk的执行方式

用户通过3种方式来执行awk程序,分别是命令行,awk脚本,可执行文件。

命令行语法 awk  'awk程序语句'  待处理的文件 。例如:awk '{ print }' a.txt

awk脚本语法 awk  -f  awk脚本  待处理的文件 。awk脚本里依次写上awk程序语句即可。

可执行脚本语法 awk脚本 待处理的文件 。但是一定要指定命令解释器 #! /bin/awk -f 。脚本内容依次写上awk的程序语句即可。



2.3 特殊字符

$0:表示整个当前行 

$1:每行第一个字段 

NF:字段数量变量 

NR:每行的记录号,多文件记录递增 

FNR:与NR类似,不过多文件记录不递增,每个文件都从1开始 

FS:BEGIN时定义分隔符,默认是空格或制表符。

RS:输入的记录分隔符,默认是换行符。awk每次读取一行进行处理,通过指定行分隔符,来决定awk一次读取多少行。例如:指定行分隔符为空行,awk每次读取有空格的地方。

\t:制表符 

\n:换行符 

~ :匹配,与==相比不是精确比较 

!~:不匹配,不精确比较 

== :等于,必须全部相等,精确比较 

!= :不等于,精确比较 

&&:逻辑与 

||: 逻辑或 

+:匹配时表示1个或1个以上 

/[0-9][0-9]+/: 两个或两个以上数字 

/[0-9][0-9]*/ : 一个或一个以上数字 

OFS:输出字段分隔符, 默认也是空格,可以改为制表符等 

ORS:输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕 

-F ':' :指定分隔符



3.awk的模式匹配

awk的匹配模式主要包括关系表达式,正则表达式,混合模式,BEGIN模式,END模式等。



3.1 关系表达式

awk提供了许多关系运算符,例如大于> ,小于< ,等于==等,awk可以以关系表达式作为匹配模式,当文本行满足关系表达式时,则会执行响应的操作。


实例:

显示第二段大于80的行。

# awk '$2 > 80 { print }' 1.txt

q       90

e       86

r       84

y       98

表示第二列的值大于80,执行花括号里面的 print 操作。



3.2 正则表达式

awk支持正则表达式匹配,和sed一样,需要放在两条斜线 /xx/ 之间。


实例:

# awk '/^(w|r)/ { print }' 1.txt  

w       75

r       84

表示匹配w或r 并 print 出来。



3.3 混合模式

awk支持关系表达式和正则表达式,同时支持使用逻辑运算符。

&&:逻辑与

||:逻辑或

!:逻辑非


实例:

# awk '/^w/ && $2 > 70 { print }' 1.txt    

w       75

两条匹配模式都为真,才会显示。


# awk '/^w/ || /^r/ { print }' 1.txt

w       75

r       84

两条匹配模式哪条为真显示哪条。都为真都显示。



3.4 区间模式

区间模式是显示两条匹配模式之间的文本行。格式如下:

匹配模式1,  匹配模式2


实例:

匹配root开头的行和UID为3之间的行。-F指定分隔符。

# awk -F ":" '/^root/, $3==3 { print }' passwd

root:x:0:0:root:/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



3.5 BEGIN模式

BEGIN模式是一种内置的模式,该模式里的内容生命周期只会被执行一次,一般用在脚本里面。语法如下:

#! /bin/awk -f

BEGIN {

执行的操作1

执行的操作2

...

}

{ 对待处理的文件执行的操作 }

写成一行就是:

awk 'BEGIN { 执行的操作1; 执行的操作2; } { 对待处理的文件执行的操作 }'  待处理的文件


实例:

只使用BEGIN模式显示内容。

# awk 'BEGIN { print "aaa"; print "=======" }'

aaa

=======


使用BEGIN模式同时文件进行操作。

# awk 'BEGIN { print "aaa"; print "=======" } { print }' 1.txt  

aaa

=======

q       90

w       75

e       86



3.6 END模式

END模式也生命周期只会执行一次。一般会把善后的工作放在END模式对应模块里。在执行END模块之前,必须执行操作或者执行BEGIN模式, 语法如下:

#! /bin/awk -f

{ 对待处理的文件执行的操作 }

END {

执行的操作1

执行的操作2

...

}

写成一行就是:

awk ' { 对待处理的文件执行的操作 }  END { 执行的操作1; 执行的操作2; }'  待处理的文件


实例:

执行END模式,前面必须有操作,不然不能执行。

# awk '{ print } END { print "aaa"; print "=======" }' 1.txt

q       90

w       75

e       86

aaa

=======


执行BEGIN模式和END模式

# awk 'BEGIN { print "aaa"; print "=======" } END { print "======="; print "aaa" }' 1.txt  

aaa

=======

=======

aaa



4. 变量

awk的变量包括自定义的变量和系统内置变量。



4.1 自定义变量和引用

要放在BEGIN模式里面,不然不会执行成功。引用变量直接跟变量名即可。

# awk 'BEGIN { x=3; print x }'

3



4.2 系统内置变量

变量

说明

$0

表示当前整个文件的内容

$n

n是整数,表示字段,每行第N个字段 

NF

表示当前记录的字段数,字段总数

NR

每行的记录号,多文件记录递增,总行数

FNR

与NR类似,不过多文件记录不递增,每个文件都从1开始 

OFS

写在条件的前面,用来指定print显示的列之间的分隔符。例如:awk -F ":" '{OFS="#"} $1=="root"  {print $1,$2,$3,$4}' test.txt

FILENAME

表示正在处理的数据文件的名称

FS

字段分隔符,默认是空格或制表符

RS

行分隔符,默认是换行符。awk每次读取一行进行处理,通过指定行分隔符,来决定awk一次读取多少行。例如:指定行分隔符为空行,awk每次读取有空格的地方。



4.3 内置变量行分隔符FS 字段分隔符RS

awk对文本进行处理是一行一行选取的,然后对文本行进行处理。

因为系统变量FS默认的分隔符是换行符“\n”,如果更改换行符则会每次读取到换行符的位置。

一般把 FS 和 RS 放在BEGIN 模块里面。


实例1:

指定A为分割符,所以在处理后的A都换行符,而不出现了。

ccc下面的空格是文件本身的换行符\n。

# cat 1.txt

aaaAbbbAccc

# awk '{ print } { print "===="}' 1.txt //正常显示

aaaAbbbAccc

====

# awk 'BEGIN { RS="A" } { print }{ print "===="}' 1.txt //指定RS之后

aaa

====

bbb

====

ccc

====


实例2:

把A当做字段分割符,显示第一段,则第一个A前面的内容为第一个字段符。

# cat 1.txt

a a a A b b b A c c c

# awk  '{ print $1 }' 1.txt //正常显示

a

# awk 'BEGIN { FS="A" } { print $1 }' 1.txt //指定FS之后。空格不再是分隔符了。

a a a


实例3:

匹配第三段大于500的行,print 第137段,分隔符用#。

# awk -F ":" '$3>500 { print $1"#"$3"#"$7}' test.txt

nfsnobody#4294967294#/sbin/nologin

mysql#501#/sbin/nologin

# awk -F ":" '{OFS="#"}$3>500 { print $1,$3,$7}' test.txt      

nfsnobody#4294967294#/sbin/nologin

mysql#501#/sbin/nologin



4.4 记录$0 ,字段$n 的引用

在awk中,用户可以使用系统变量引用记录和字段。

虽然awk每次读取的是一行,但在程序中记录和字段的引用都是针对当前整个文件或数据流来说的。也就是如果要显示第一段会显示整个文件的第一段。


实例1:

变量$0的值就是当前的记录值,可以说是当前文件或者数据流的内容。

# awk '{ print $0 }' 1.txt  

wang    85      92      79      87

li      89      90      73      82

zhao    81      88      92      81


实例2:

$1 $2 $3 分别代表第一列 第二列 第三列的数值。可以使用变量把数值的值相加。

# awk '{ print $1, $2+$3+$4+$5}' 1.txt

wang 343

li 334

zhao 342



5.运算符和表达式

5.1 算术运算符

运算符

说明

举例

+

加法

1+2,表示求1和2的和,得3

-

减法

2-1,表示求2和1的差,得1

*

乘法

2*5,表示求2和5的积,得10

/

除法

6/2,表示求6和2的商,得3

%

求余

5/2,表示求5除以2的余,得1

^

幂运算

2^3,表示求2的3次方,得8


实例:

# awk ' BEGIN { print 3^2 , 5%2 , 5/2 , 2*3 } '

9  1  2.5  6



5.2 赋值运算

运算符

说明

举例

=

赋值

x=5,表示给x赋值为5

+=

前后相加后,再赋值给变量

x+=5,表示x的值加上5,再赋值给x,等价x=x+5

-=

前数值减后面数值,再赋值给变量

x-=5,表示x的值减5,再赋值给x

*=

前后相乘后,再赋值给变量

x*=5,表示x的值乘5,再赋值给x

/=

前数值除以后面数值,再赋值给变量

x/=5,表示x的值除以5,再赋值给x

%=

前数值除以后面数值的余,赋值给变量

x%=5,表示x的值除以5的余数,再赋值给x

^=

前数值的后面数值的次方,赋值给变量

x^=5,表示x的值的5次方,再赋值给x


实例:

# awk ' BEGIN { print x=5 , x+=5 , x%=6 , x*=3 } '

5 10 4 12



5.3 条件运算符

即当表达式的值为真时,返回数值1,否则返回数值2。语法如下:

变量=(表达式?"数值1":"数值2")

print 变量


实例:

判断打印成绩单中的数值是否大于85,大于90的给A,否则给B。

# awk '{ a=($2>85?"A":"B"); print a }' 1.txt  

B

A

B

# awk '{ a=($2>85?"A":"B"); print $1,a }' 1.txt

wang B

li A

zhao B



5.4 逻辑运算符

awk支持3种逻辑运算,分别是逻辑与,逻辑或和逻辑非。

运算符

说明

举例

&&

逻辑与,两个表达式都为真时,运行结果才为真

1>2&&3>2的值为假

||

逻辑或,有一个为真,运行结果为真。两个表达式都为假时,运行结果为假

1>2||3>2的值为真

!

逻辑非,当表达式为真是,运行结果为假。当表达式为假时,运行结果为真

!(1>2)的值为真


实例:

当所有字段的数值都大于80时,才显示出来。

# awk '$2 > 80 && $3 > 80 && $4 > 80 && $5 > 80 { print } ' 1.txt  

zhao    81      88      92      81



5.5 关系运算

awk支持关系运算一般有:大于,小于,等于 等..

运算符

说明

举例

>

大于

5>2的值为真

>=

大于等于

8>=8的值为真

<

小于

5<6的值为真

<=

小于等于

5<=7的值为真

==

等于

5==5的值为真

!=

不等于

1!=2的值为真

~

匹配

$1~/^T/表示匹配第一个字段以字符T开头的记录

!~

不匹配

$1!~/a/表示匹配第一个字段不包含字符a的记录

匹配运算符~ 不匹配运算符!~是awk特有的关系运算符,语法如下:

字符串 ~ 表达式

字符串 !~ 表达式

匹配运算符:判断字符串中是否包含表达式的字符串。

不匹配运算符:判断字符串中是否不包含表达式的字符串。



实例:

匹配第一个字符l开头的记录。

# awk '$1~/^l/ { print }' 1.txt

li      89      90      73      82

匹配前十行,第一段包含是root或者lp的行

# awk -F ":" 'NR<=10 && $1 ~ /root|lp/' test.txt  

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

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin


以上是关于awk命令的主要内容,如果未能解决你的问题,请参考以下文章

如何在Linux中使用awk命令

精通awk系列:awk命令结构和awk语法结构

Linux入门系列——awk命令详解

shell命令三剑客之awk命令详解,cut命令,linux里记录行踪(操作记录)

linux awk命令详解

利用awk命令进行统计