Linux--awk命令详解

  awk是一个强大的文本分析工具awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk

  awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

命令格式

awk [options] program file

  1. options :选项
  2. program :程序
  3. file:文件(需要处理的数据文件)
  • awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

调用awk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1. 命令行方式
awk [-F field-separator] '{commands}' file
===> [-F域分隔符]是可选的,commands 是真正awk命令,file 是待处理的文件。
===> 在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。
===> 通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

2. shell脚本方式
将所有的awk命令插入一个文件,使程序可执行,然后awk命令解释器作为脚本的首行,通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/bash
可以换成:#!/bin/awk

3. 将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file file
其中,-f选项加载awk-script-file中的awk脚本

awk处理文本

awk的基本特性之一就是它处理文本文件中数据的能力。它会自动给每行中的每个数据元素分配一个变量。

$0: 代表整个文本行
$1: 代表文本行中的第1个数据字段(第一个域)
$2: 代表文本行中的第2个数据字段
$n: 代表文本行中的第n个数据字段

  • 注意:每个数据字段在文本行中都是通过字段分隔符来划分的。awk中的默认字段分隔符是任意的空白字符(例如空格或制表符)
  • 如果想要读取使用其他字段分隔符的文件可以使用-F 选项指定:awk -F: '{print $1}' /etc/passwd
  • 实例一,默认字段分隔符
      

下面我们来取head_7.log的第一个域和第七个域,如图:awk ‘{print $1,$7 }’ head_7.log

  

  • 实例二,使用自己的分隔符
    来看一看默认的/etc/passwd文件
      

取出第一和第七域

  

awk脚本

awk编程语言允许你将多条命令组成一个脚本程序。把多条命令保存到一个文件中,这个文件我们就称为awk的脚本文件

格式:只要将每条命令放到一个新的行就好了,不需要用分号。
awk -F: -f script /etc/passwd
这里的script是一个文件,需要使用-f参数指定

  

BEGIN|END

BEGIN: 有时可能需要在处理数据前运行脚本,比如为报告创建开头部分。
END: 跟BEGIN关键字类似,END关键字允许你指定一个程序脚本,awk会在读完数据后执行它。

awk内置变量

FS: Field Seperator, 输入时的字段分隔符
RS: Record Seperator, 输入行分隔符
OFS: Output Field Seperator, 输出时的字段分隔符;
ORS: Outpput Row Seperator, 输出时的行分隔符;
NF: Numbers of Field,字段数量
NR: Numbers of Record, 行号;所有文件的一并计数;
FNR:行号;各文件分别计数;

awk进阶

正则表达式

() {} ##不支持
. * ^ $ ? + [] | \< > () ##可以直接使用

1
2
3
4
5
6
7
8
9
[momo1@momo1 shell]$ awk -F: '/^root/{print $1,$7}' /etc/passwd
root /bin/bash

[momo1@momo1 shell]$ awk -F: '!/^root/{print $1,$NF}' /etc/passwd|head -5
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync

关系运算符

/> < == != >= <=
~(匹配) !~(不匹配)

1
2
3
4
5
6
[momo1@momo1 shell]$ awk -F: '$3 == 0 {print $1}' /etc/passwd
root

[momo1@momo1 shell]$ awk -F: '$3 != 0{ print $1}' /etc/passwd | head -2
bin
daemon

逻辑运算符

&& || ! ##与 或 非

1
2
3
[momo1@momo1 shell]$ awk -F: '$3 > 0 && $3 < 10 {print $1, $3}' /etc/passwd |head -2
bin 1
daemon 2

算数运算符

+-*/%(取模(余数)) ^(幂运算)

awk流控制|循环

简单的条件判断

语法:(表达式 ? 值1 : 值2) 如果表达式成立,输出值1;否则输出值2

1
2
3
4
5
6
7
8
9
[root@momo ~]# cat num
2 8 9
8 4 6
3 5 7

[root@momo ~]# awk '{print ( $1 > $2 ? $1 : $2)}' num
8
8
5

if判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
语法:
{ if ( 表达式 )
{
//......
}
}

多支判断:
{ if (表达式)
{
//......
}
else if (表达式)
{
//......
}
//......
else
{
//......
}
}

如果表达式成立,那么执行动作。

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
[root@momo ~]# awk '{if ($2>=80 && $2 <=100) {print $1,"great"} else {print $1, "good"}}' cj
tx great
tx1 great
tx2 good

[momo1@momo1 shell]$ cat ifTest.txt
zangs 95 86 86 78
lishi 89 88 85 34
wangwu 73 89 85 77
zhaoliu 80 71 65 66
qitian 75 85 69 99
wangba 78 82 89 88

##判断的标准:
90-100 A
80-89 B
70-79 C
60-69 D
0-59 E

[momo1@momo1 shell]$ awk '{ if ($2 >= 90 && $2 <= 100) {print $1,"A"} else if ($2 >= 80 && $2 < 90) {print $1,"B"} else if ($2 >= 70 && $2 < 80) {print $1,"C"} else if ($2 >= 60 && $2 < 70) {print $1,"D"} else {print $1,"E"} }' ifTest.txt
zangs A
lishi B
wangwu C
zhaoliu B
qitian C
wangba C

循环while

语法: ‘var=初值; while (表达式){ //… }’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[momo1@momo1 shell]$ awk -F: '{i=1; while (i<=NF){print $i;i++}}' /etc/passwd |head -8
root
x
0
0
root
/root
/bin/bash
bin

[momo1@momo1 shell]$ awk 'BEGIN {FS=":"}{i=NF;while(i>=2){printf $i ":";i--}print $1}' /etc/passwd | head -n 7
/bin/bash:/root:root:0:0:x:root
/sbin/nologin:/bin:bin:1:1:x:bin
/sbin/nologin:/sbin:daemon:2:2:x:daemon
/sbin/nologin:/var/adm:adm:4:3:x:adm
/sbin/nologin:/var/spool/lpd:lp:7:4:x:lp
/bin/sync:/sbin:sync:0:5:x:sync
/sbin/shutdown:/sbin:shutdown:0:6:x:shutdown

for循环

语法: { for(表达式) { //……} }
表达式:分为3部分:
(1)初始化表达式 i=1
(2)测试表达式 i<10
(3)更新测试表达式 i++

  • 语句:
    next 处理输入行的下一个输入行
    exit 退出
    continue 结束本次循环
    break 跳出循环
1
2
3
4
5
6
[momo1@momo1 shell]$ awk 'BEGIN {FS=":"}{for(i=NF;i>=2;i--){printf $i ";"};print $1}' /etc/passwd |head -n 5
/bin/bash;/root;root;0;0;x;root
/sbin/nologin;/bin;bin;1;1;x;bin
/sbin/nologin;/sbin;daemon;2;2;x;daemon
/sbin/nologin;/var/adm;adm;4;3;x;adm
/sbin/nologin;/var/spool/lpd;lp;7;4;x;lp

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器