awk提供了很强大的功能,它是linux中功能最强大的数据处理引擎之一,它不仅可以对文本数据进行搜索分析处理排序,还可以支持数学运算,含有内置函数和内置变量,甚至还可以进行一些脚本处理,编程。可以这么说,它可以根据发挥者的能力来起作用。

awk在linux中其实并不叫awk,而叫gawk

[root@libin ~]# which awk
/bin/awk
[root@libin ~]# ls -l /bin/awk
lrwxrwxrwx. 1 root root 4 Jun 29 17:14 /bin/awk –> gawk 它是链接指向gawk

awk的基本语法(基本格式):

awk  [option]…….'/PATTERN/{action}’ FILE…..

或者是awk [option]…..'script’ FILE……因为awk本身就是一个类似于解释器的东西可以解释。

而有时候 '/PATTERN/{action}'就相当于'scrpit’ 相当于awk的脚本。

awk中的变量大致分两种,一种是内置的变量,一种可以允许你自定义变量。

awk的PATTERN有下列几种涵义:

PATTERN可以做地址定界

起始行,结束行

/pattern1/,/pattern2/

还可以特定某行

/pattern/

或直接加数字表示第几行

另外PATTERN还支持表达式的功能

比如:表达式中支持:

>,<,<=,>=,!=,==,~(模式匹配的)

另外PATTERN中还有两个比较特殊的一个是BEGIN,另一个是END。

BEGIN表示在后面action之前要做的动作,这些动作可以有初始化一些变量,在输出最开始显示一些东西。

而END表示后面action之后要做的动作。下面有示例

比如:取出系统上id号大于等于300的用户有哪些?

[root@libin ~]# awk -F: '$3 >= 300{print $1,$3}' /etc/passwd
rtkit 499
saslauth 498
nfsnobody 65534
pulse 497
mageedu 500
bob 501
zabbix 496
jimmy 502

这里笔者曾经犯过一次错误,笔者在写awk的时候,并没有加上-F: 分隔符,只是写成awk ‘$3 >= 300{print $1,$3}' /etc/passwd 结果屏幕并没有输出正确的信息,只是显示:

[root@libin ~]# awk '$3 >= 300 {print $1}' /etc/passwd
dbus:x:81:81:System
vcsa:x:69:69:virtual
avahi-autoipd:x:170:170:Avahi
rpcuser:x:29:29:RPC
nfsnobody:x:65534:65534:Anonymous
pulse:x:497:496:PulseAudio
zabbix:x:496:493:Zabbix

大家在这里引以为戒吧!

例子2、显示用户shell为bash的用户(可以让用户做模式匹配)

[root@libin ~]# awk -F: '$7 ~ /bash$/{print $1,$7}' /etc/passwd (这里模式匹配引用的内容一定要加//,如/要被引用的内容/

ageedu /bin/bash
bob /bin/bash
jimmy /bin/bash
bigbing /bin/bash
mysql /bin/bash

例子3、在例子2的显示内容之前加上一句话how are you

[root@libin ~]# awk -F: 'BEGIN{print "how are you"}$7 ~ /bash/ {print $1,$7}' /etc/passwd
how are you
root /bin/bash
mageedu /bin/bash
bob /bin/bash
jimmy /bin/bash
bigbing /bin/bash

注意这里如果想加入字串,一定要用双引号引出来,不然就会变成这样,比如笔者曾经忘记加双引号,结果就显示空白了。如

image

加上END试试:

awk -F: 'BEGIN {print "hello"}$7 ~ /bash$/{print $1,$7}END{print "thats all"}' /etc/passwd
hello
root /bin/bash
mageedu /bin/bash
bob /bin/bash
jimmy /bin/bash
bigbing /bin/bash
thats all

这里曾经笔者也犯过一个错误:在被引用的字串里使用了that’s all,就因为这个不起眼的 ’的符号,导致结果并没有输出出来。

image 所以一般没有必要给自己找麻烦就不用特殊符号。


在awk有很多内置变量:

NF:Number of Field 字段数,直接引用则表示每一行中字段的总数,是个具体的数字。

FS:Field Seperator,输入分隔符

OFS Output Field Seperator 输出的分隔符

在示例中多次引用passwd这个文件,但是多次例子中输出到屏幕上的分隔都是空格,如:

root /bin/bash
mageedu /bin/bash

如果我想让它以原始的文本输出到屏幕上的”:”号呢?

[root@libin ~]# awk 'BEGIN{FS=":";OFS=":"}$1~/root$/{print $1,$7}END{print "admin"}' /etc/passwd
root:/bin/bash
admin

这里就用FS取代了-F选项,并指定输出的分隔符为:

 

 

在awk中,引用变量的值,不需要以$开头,如果以$开头的变量,则是引用变量中的字段的值。

awk大致的工作模式是这样的:

image 如果不是特别说明,awk会默认以空白字符作为分隔符,逐行的去做字符段的匹配。

而awk有自己内置的变量:举例来说:

image  如左图,假设line1有4个字段,默认以空白分隔符分隔,对于第一个字段,awk把它理解为$1,第二个字段,理解为$2,以此类推。这里比较特殊一点就是$0,它表示全部字段的内容。我们打个比方:

我们写一个示例:

[root@libin ~]# cat awk1.txt
tom and jerry are playing in the garden
[root@libin ~]#

这是一个只有一行的文本,下面用awk来进行取变量:

step1、先取出$1:

[root@libin ~]# awk -F' ' '{print $1}' ./awk1.txt 
tom                                                               如果没有特殊要求,它默认是以空白为分隔符的,所以-F ‘ ‘ 可以进行省略。

[root@libin ~]# awk  '{print $1}' ./awk1.txt
tom

step2、取出第一和第三个字段

[root@libin ~]# awk '{print $1,$3}' ./awk1.txt
tom jerry                                                        这里使用,号隔开的,其结果输出到标准输出(屏幕)上时,出现了tom jerry,这里如果我们不使用,会是什么样子的效果?

step3、如果在{}中$1和$3之间不加符号隔开

[root@libin ~]# awk '{print $1$3}' ./awk1.txt
tomjerry                                                         这里tomjerry被粘合在了一起

设想,如果我们人为的加些符号在里面,可以出现什么效果呢?

[root@libin ~]# awk '{print $1-$3}' ./awk1.txt 这里加上 - 符号
0
[root@libin ~]# awk '{print $1is$3}' ./awk1.txt 这里加上了 is
tomjerry
[root@libin ~]# awk '{print $1&&$3}' ./awk1.txt 这里加上&&符号
1
[root@libin ~]# awk '{print $1 $3}' ./awk1.txt  这里加上了空白字符
tomjerry

输出都不尽相同,可见符号在awk的{}有着不同的意思。以后在使用awk的时候务必要小心,否则一个不注意有可能就得不到想要的结果。

step4、如果我想整行都显示出来

[root@libin ~]# awk '{print $0}' awk1.txt
tom and jerry are playing in the garden           这里的效果类似grep ‘[[:alnum:]]\+’ awk1.txt

step5、有一个变量叫做NF,我如果在awk的program中写入NF表示什么呢?

[root@libin ~]# awk '{print NF}' awk1.txt
8

出现了数字8,再仔细看看文本中 tom and jerry are playing in the garden 以空格分开一共8段,原来NF表示每一行里字段的总个数。

step5、那么$NF是什么呢?

[root@libin ~]# awk '{print $NF}' awk1.txt
garden                                                    对照tom and jerry are playing in the garden字段,原来$NF表示每一行里最后一个字段的内容。

step6、显示gid小于500的组

[root@libin ~]# awk -F: 'BEGIN{print "this is context"}$3 < 500{print $1,$3}' /etc/passwd
this is context
root 0
bin 1
daemon 2

或者

[root@libin ~]# awk 'BEGIN{FS=":";print "this is context"}$3 < 500{print $1,$3}' /etc/passwd
this is context
root 0
bin 1
daemon 2

step7、显示默认shell为nologin的用户:

awk 'BEGIN{FS=":"}$7~/nologin$/{print$1,$7}' /etc/passwd
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin

step8、显示eth0网卡配置文件的配置信息,只显示=后面的内容

[root@libin ~]# awk 'BEGIN{FS="="}{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0
eth0
dhcp
00:0c:29:7b:06:ec
yes
yes
Ethernet
172.16.249.126

step9、显示/etc/sysctl.conf文件中定义的内核参数的参数名称

[root@libin ~]# awk '$1~ /kernel.*/{print $1}' /etc/sysctl.conf
kernel.sysrq
kernel.core_uses_pid
kernel.msgmnb
kernel.msgmax
kernel.shmmax
kernel.shmall

step10、显示eth0网卡的ip地址

[root@libin ~]# ifconfig eth0 | awk -F: '$1 ~ /inet addr.*/ {print $1,$2}' | awk '{print $1,$2,$3}'
inet addr 192.168.1.146

如上是awk的最基础的用法,下篇还有awk的高级用法。