1.简单实例
awk逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行你想要的操作
awk基本结构包括模式匹配(用于找到要处理的行)和处理过程(即处理动作)。
pattern {action}
行为用{}包括住,awk后面的模式加操作用单引号包括。
1
2
3
4
5
6
7
8
9
10
11
12
|
[nxuser@PSBJ-0-0-0 pstests]$ cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=PSBJ-0-0-0
NOZEROCONF=yes
NETWORKING_IPV6=yes
IPV6_AUTOCONF=no
GATEWAY=135.252.172.1
备注:打印包含主机名的行,因为没有指定动作指令,默认动作为打印。
[nxuser@PSBJ-0-0-0 pstests]$ awk '/HOSTNAME/' /etc/sysconfig/network
HOSTNAME=PSBJ-0-0-0
[nxuser@PSBJ-0-0-0 pstests]$ awk '/HOSTNAME/ {print "find it!"}' /etc/sysconfig/network
find it!
|
也可以写好awk命令的shell脚本,然后利用-f参数调用 ,如下所示
1
2
3
4
5
|
[nxuser@PSBJ-0-0-0 pstests]$ cat findhostname.sh
/HOSTNAME/ {print "find it!"}//注意去掉单引号,否则报错
[nxuser@PSBJ-0-0-0 pstests]$ awk -f findhostname.sh /etc/sysconfig/network
find it!
|
2.基本操作
1,。awk一次从文件中读取一条记录,并将记录存储在字段变量$0中。记录被分割为字段并存储在$1,$2 ..., $NF中(默认使用空格或制表符为分隔符)。
内建变量NF为记录的字段个数,此处
1
2
3
4
5
6
7
8
|
[nxuser@PSBJ-0-0-0 pstests]$ echo hello world |awk '{print $1,$2}'
hello world
[nxuser@PSBJ-0-0-0 pstests]$ echo hello world |awk '{print NF}' 2
[nxuser@PSBJ-0-0-0 pstests]$ echo hello world |awk '{print $NF}'
world
|
2. 默认awk读取数据以空格或制表符作为分隔符,但可以通过-F或FS(field separator)变量来改变分隔符。
示例:
awk -F 分隔符 '{print $1}'
或者 awk 'BEGIN {FS=":"} {print $1}'
1
2
3
4
5
|
[nxuser@PSBJ-0-0-0 pstests]$ echo hello:world |awk -F: '{print $1}'
hello
[nxuser@PSBJ-0-0-0 pstests]$ echo hello:world |awk 'BEGIN {FS=":"} {print $1}'
hello
|
多个分隔符,利用 {FS="[:,]"}表示,如下
1
2
|
[nxuser@PSBJ-0-0-0 pstests]$ echo hello:world,ok |awk 'BEGIN {FS="[:,]"} {print $1,$2,$3}'
hello world ok
|
3. 内置变量
以下为awk内置变量:
ARGC 命令行参数个数
FILENAME 当前输入文档的名称
FNR 当前输入文档的当前记录编号,尤其当有多个输入文档时有用
NR 输入流的当前记录编号
NF 当前记录的字段个数
FS 字段分隔符
OFS 输出字段分隔符,默认为空格
ORS 输出记录分隔符,默认为换行符\n
RS 输入记录分隔符,默认为换行符\n
1
2
3
4
5
6
7
8
9
10
11
12
|
[nxuser@PSBJ-0-0-0 tmp]$ awk '{print FILENAME}' testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
testfunction.sh
|
1
2
3
4
5
6
7
|
[nxuser@PSBJ-0-0-0 tmp]$ awk '/HOSTNAME/' /etc/sysconfig/network
HOSTNAME=PSBJ-0-0-0
[nxuser@PSBJ-0-0-0 tmp]$ awk '/HOSTNAME/ {print $1}' /etc/sysconfig/network
HOSTNAME=PSBJ-0-0-0
[nxuser@PSBJ-0-0-0 tmp]$ awk -F= '/HOSTNAME/ {print $1}' /etc/sysconfig/network
HOSTNAME
[nxuser@PSBJ-0-0-0 tmp]$
|
4. 表达式与操作符
表达式是由变量、常量、函数、正则表达式、操作符组成,awk中变量有字符变量和数字变量。如果在awk中定义的变量没有初始化,则初始值为空字串或0。
注意:字符操作时一定记得需要加引号
1) 变量定义示例:
a="welcome to beijing"
b=12
2) 操作符(awk操作符与C语言类似)
+ 加
- 减
* 乘
/ 除
% 取余
^ 幂运算
++ 自加1
-- 自减1
+= 相加后赋值给变量(x+=9等同于x=x+9)
-= 相减后赋值给变量(x-=9等同于x=x-9)
*= 相乘后赋值给变量(x*=9等同于x=x*9)
/= 相除后赋值给变量(x/=9等同于x=x/9)
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于
!= 不等于
~ 匹配
!~ 不匹配
&& 与
|| 或
-F 指定分隔符,有END最后输出统计结果,否则输出每行的结果
1
|
[nxuser@PSBJ-0-0-0 tmp]$ awk '/aaaa/ {x+=1} END {print x}' test.txt
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[nxuser@PSBJ-0-0-0 tmp]$ cat test.txt
aaaa
bbbb
cccc
dddd
aaaa
bbbb
cccc
dddd
[nxuser@PSBJ-0-0-0 tmp]$ awk '/aaaa/ {print x+=1}' test.txt
1
2
[nxuser@PSBJ-0-0-0 tmp]$ awk '/aaaa/ {x+=1} END {print x}' test.txt
2
[nxuser@PSBJ-0-0-0 tmp]$ awk -F: '$3>500 {print $1}' /etc/passwd
|
5 循环
1. {if(xxx) print xxx ; else xxx}以分号分隔
1
2
|
[nxuser@PSBJ-0-0-0 tmp]$ cat /etc/passwd |grep mysql | awk -F: '{if($3>100) print $3; else print "too small"}'
31034
|
2. for 循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
[nxuser@PSBJ-0-0-0 tmp]$ awk 'BEGIN {for(i=1;i<=10;i++) print i}' test.txt
1
2
3
4
5
6
7
8
9
10
[nxuser@PSBJ-0-0-0 tmp]$ awk '{for(i=1;i<=10;i++) print i}' test.txt
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
[nxuser@PSBJ-0-0-0 tmp]$ vi test.txt
aaaa
bbbb
cccc
dddd
aaaa
bbbb
cccc
dddd
|
3. while循环
1
2
3
4
5
6
7
8
9
10
11
12
|
[nxuser@PSBJ-0-0-0 tmp]$ awk 'BEGIN { while (i<=10) {++i; print i}}'
1
2
3
4
5
6
7
8
9
10
11
|
6 应用场景
使用 awk 场景举例
统计浏览器类型
如果我们想知道那些类型的浏览器访问过网站,并按出现的次数倒序排列,我可以使用下面的命令:
awk -F\" '{print $6}' access.log | sort | uniq -c | sort -fr
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[nxuser@PSBJ-0-0-0 tmp]$ cat assess.log
nxuser:firefox:201304001
root:IE:201304001
nxuser:firefox:201304001
root:IE:201304001
root:IE:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
root:IE:201304001
root:IE:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
root:IE:201304001
root:IE:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
root:IE:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
|
比如上述是访问log,按统计浏览器类型统计次数,如下
-c 参数显示文件中每行连续出现的次数。所以先用sort排序,然后用uniq -c 统计次数。如果不用sort,不能实现统计。因为uniq是统计每行连续出现的次数
uniq命令不加任何参数,仅显示连续重复的行一次
1
2
3
4
5
6
|
[nxuser@PSBJ-0-0-0 tmp]$ awk -F: '{print $2}' assess.log |sort | uniq -c
13 IE
12 firefox
[nxuser@PSBJ-0-0-0 tmp]$ awk -F: '{print $2}' assess.log |sort | uniq
IE
firefox
|
备注:
sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式:
sort [-bcfMnrtk][源文件][-o 输出文件]
补充说明:sort可针对文本文件的内容,以行为单位来排序。
参 数:
-b 忽略每行前面开始出的空格字符。
-c 检查文件是否已经按照顺序排序。
-f 排序时,忽略大小写字母。
-M 将前面3个字母依照月份的缩写进行排序。
-n 依照数值的大小排序。
-o<输出文件> 将排序后的结果存入指定的文件。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
-k 选择以哪个区间进行排序。
7 测试sort命令
sort -u 去除重复 ,如下:
1
2
3
|
[nxuser@PSBJ-0-0-0 tmp]$ sort -u assess.log
nxuser:firefox:201304001
root:IE:201304001
|
不带任何参数,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[nxuser@PSBJ-0-0-0 tmp]$ sort assess.log
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
|
sort -r sort默认的排序方式是升序,如果想改成降序,就加个-r就搞定了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[nxuser@PSBJ-0-0-0 tmp]$ sort -r assess.log
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
root:IE:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
nxuser:firefox:201304001
|
(责任编辑:IT)