awk基本应用回顾

一、AWK简介:

AWK是一个文本报告生成器,它不仅是Linux中也是任何环境中现有的功能最强大的数据处理引擎之一,它具有编程及数据操作语言,提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、过程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。它允许使用者创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表等等功能。

在最初创造AWK时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。AWK会扫描文件中的每一行,查找与命令行中所给定内容相匹配的内容,如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。

二、AWK语法:

awk [option]...'/PATTERN/{action}' FILE;语法中'/PATTERN/{action}'部分又被称为awk的脚本。

三、AWK基本应用示例:

1、打印文本文件的某个字段,默认分隔符为空格:

[root@client2 html]# awk '{print $1}' /etc/fstab
#
#
#
#
#
#
#
/dev/mapper/vg0-root
UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3
/dev/mapper/vg0-usr
/dev/mapper/vg0-var
/dev/mapper/vg0-swap
tmpfs
devpts
sysfs
proc

2、打印文本文件的多个字段:

[root@client2 html]# awk '{print $1,$2}' /etc/fstab 
 
# 
# /etc/fstab
# Created
# 
# Accessible
# See
# 
/dev/mapper/vg0-root /
UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3 /boot
/dev/mapper/vg0-usr /usr
/dev/mapper/vg0-var /var
/dev/mapper/vg0-swap swap
tmpfs /dev/shm
devpts /dev/pts
sysfs /sys
proc /proc

3、打印所有字段,$0用于引用所有字段:

[root@client2 html]# awk '{print $0}' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Mon Jul 28 19:06:01 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/vg0-root    /                       ext4    defaults        1 1
UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3 /boot                   ext4    defaults        1 2
/dev/mapper/vg0-usr     /usr                    ext4    defaults        1 2
/dev/mapper/vg0-var     /var                    ext4    defaults        1 2
/dev/mapper/vg0-swap    swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0

4、显示指定的某行的某字段信息或打印连续的若干行:

[root@client1 ~]# awk 'NR==10{print $1}' /etc/fstab
UUID=3c74d332-e31d-4368-9e07-74479e1c4ad3
[root@node1 pam.d]# awk 'NR==8,NR==12' /etc/fstab
#
/dev/mapper/vg0-root    /                       ext4    defaults        1 1
UUID=fbb4629b-1279-4a2a-9f49-18faa0e5bece /boot                   ext4    defaults        1 2
/dev/mapper/vg0-usr     /usr                    ext4    defaults        1 2
/dev/mapper/vg0-var     /var                    ext4    defaults        1 2

5、NF(Number of Field) 打印每行有几个字段,变量NF用于表示一行内的字段数,在AWK中引用变量时不需要加$,但是如果变量前加了$,如NF,那么就是引用对应的字段的:

[root@client2 html]# awk '{print NF}' /etc/fstab
0
1
2
10
1
9
12
1
6
6
6
6
6
6
6
6
6

6、每行中最后一个字段的调用方式为$NF:

[root@client2 html]# awk '{print $NF}' /etc/fstab
#
/etc/fstab
2014
#
'/dev/disk'
info
#
1
2
2
2
0
0
0
0
0

7、FS:Field Seperator,输入分隔符,默认是空格:


8、OFS:输出时的字段分隔符
9、语法表达式的/PATTERN/可以使用比较表达式,表达式用>,>=,<,<=,!=,==,~等比较字符来连接,比较的字符串与比较字符不需要用空格隔开,表达式也是正确的:

[root@client2 html]# awk -F: '$3 >= 500{print $1}' /etc/passwd
nfsnobody
[root@client2 html]# awk -F: '$3 < 500{print$1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
uucp
operator
games
gopher
ftp
nobody
dbus
usbmuxd
vcsa
rtkit
rpc
avahi-autoipd
abrt
haldaemon
gdm
ntp
apache
saslauth
postfix
rpcuser
pulse
sshd
tcpdump
[root@client2 html]# awk -F: '$3 == 0{print $1}' /etc/passwd
root

10、模式匹配示例:AWK的模式与action字段之间不需要空格分开,比较表达式两端与比较表达式字符之间不需要空格,而action与要处理的字段之间也不需要空格,整个表达式都连在一起也是正确的,只是属于模式匹配的部分用//括起来,属于action字段的要用{}括起来:

[root@client2 html]# awk -F: '$7~/bash$/{print$1}' /etc/passwd
root

11、显示不相邻的多个字段,$1$7连在一起,$1 $7用空格分隔,$1,$7用逗号分隔,注意看显示的效果:

[root@client2 ~]# awk -F: '$7~/bash$/{print$1$7}' /etc/passwd
root/bin/bash
[root@client2 ~]# awk -F: '$7~/bash$/{print$1 $7}' /etc/passwd
root/bin/bash
[root@client2 ~]# awk -F: '$7~/bash$/{print$1,$7}' /etc/passwd
root /bin/bash

12、AWK中的action字段可以有多个,多个action字段要用{}括起来,比如,在输出的字段前输出表头:

[root@client1 ~]# awk -F: 'BEGIN{print"username shell"}$7~/bash$/{print$1,$7}' /etc/passwd
username shell
root /bin/bash

下面这条语句是自己测试的语句,写法是错误的,计算机在识别用户输入的命令时所做的语法分析是命令选项参数,参数中又有相对应的格式要求,比如模式和action,而下面语句中的action放在了前面,那么计算机在识别整个字符串的时候就会认为是一个命令加了一个要处理的参数,而我们要表达的模式匹配用来匹配某些行的效果就出不来了,这个字段要写在action的前面,而不能在后面出现,它被计算机识别为了其他的不能识别的字符。而如果要在action中使用多个命令,可以使用;来分隔多个action,模式也是一样,也是用;来分隔开,但是总体上来说,模式和action要有前有后,不能混乱,如果在做模式匹配前,先对行进行一些处理操作,需要使用BEGIN模式,如果要在行处理之后做一些操作就要使用END模式,BEGIN模式是打破了常规的语法顺序的,但是在程序的内部机制上被识别和匹配,而不是语法错误。

[root@client1 ~]# awk -F: '{print"username shell"}$7~/bash$/{print$1,$7}' /etc/passwd

13、显示以bash结尾的且该行的第三字段数值小于500的行的第1和第3字段:

[root@client1 ~]# awk -F: '$7~/bash$/&&$3<500{print$1,$3}' /etc/passwd
root 0

14、显示以bash结尾且该行第三个字段数值大于500的行的第1,第3,第7字段:

[root@client1 ~]# awk -F: '$7~/bash$/&&$3>500{print$1,$3,$7}' /etc/passwd

15、显示第三字段数值小于500的行的第1,第3,第7字段,结果中可以看到只有root用户是以bash结尾,所以之前的awk语句的写法是正确的:

[root@client1 ~]# awk -F: '$3<500{print$1,$3,$7}' /etc/passwd
root 0 /bin/bash
bin 1 /sbin/nologin
daemon 2 /sbin/nologin
adm 3 /sbin/nologin
lp 4 /sbin/nologin
sync 5 /bin/sync
shutdown 6 /sbin/shutdown
halt 7 /sbin/halt
mail 8 /sbin/nologin
uucp 10 /sbin/nologin
operator 11 /sbin/nologin
games 12 /sbin/nologin
gopher 13 /sbin/nologin
ftp 14 /sbin/nologin
nobody 99 /sbin/nologin
dbus 81 /sbin/nologin
usbmuxd 113 /sbin/nologin
vcsa 69 /sbin/nologin
rtkit 499 /sbin/nologin
rpc 32 /sbin/nologin
avahi-autoipd 170 /sbin/nologin
abrt 173 /sbin/nologin
haldaemon 68 /sbin/nologin
gdm 42 /sbin/nologin
ntp 38 /sbin/nologin
apache 48 /sbin/nologin
saslauth 498 /sbin/nologin
postfix 89 /sbin/nologin
rpcuser 29 /sbin/nologin
pulse 497 /sbin/nologin
sshd 74 /sbin/nologin
tcpdump 72 /sbin/nologin

16、BEGIN模式示例,只有BEGIN模式字符开头,后面从能用{}括起来action,后面从有可能再从头查找PATTERN字串:

[root@client1 ~]# awk -F: 'BEGIN{print"username,shell"}$7~/bash$/{print$1,$7}' /etc/passwd
username,shell
root /bin/bash

要注意多个要显示的字段或者字符串之间如果要用逗号分隔,那么表示他们是不同的字段,如果未指定就要用默认的分隔符分隔开显示,如果这些字段之间没有用逗号分隔,那么默认他们就被连起来显示,在AWK中要表示多个连续的字段,没有类似于其他表达方式的-等等连接符,只能是用其他的方式去遍历需要显示的多个字段。

[root@client1 ~]# awk -F: 'BEGIN{print"username,shell"}$7~/bash$/{print$1,$7}END{print"=====end====="}' /etc/passwd
username,shell
root /bin/bash
=====end=====

17、BEGIN模式:在{action}开始之前执行一次,制作表头;

END模式:在{action}结束之后执行一次,制作表尾;

要从程序的运作机制角度去考虑语句的写法会很容易记忆,写语句时也不容易出错。

而通常情况下BEGIN模式是用来指定输入分隔符和输出分隔符的,用法如下:

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

注意:BEGIN模式和END模式后面的模式字段要用{}括起来,里面的分隔符要用“”引起来表示其为前面变量的值,没有该“”是语法错误,在awk中大写的字符都是有特殊意义的,所以为这个变量赋值的方式就决定了要这样去用,否则就是错误,同样,多个变量之间的赋值操作要用;隔开,否则也是语法错误,都要注意!













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章