Linux三剑客-AWK

1、什么是awk

AWK是一种处理文本文件的语言,是一个强大的文本分析工具。有统计和计算功能。

之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

参数说明

选项参数说明:

    -F fs or --field-separator fs
    指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
    -v var=value or --asign var=value
    赋值一个用户定义变量。
    -f scripfile or --file scriptfile
    从脚本文件中读取awk命令。
    -mf nnn and -mr nnn
    对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
    -W compact or --compat, -W traditional or --traditional
    在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
    -W copyleft or --copyleft, -W copyright or --copyright
    打印简短的版权信息。
    -W help or --help, -W usage or --usage
    打印全部awk选项和每个选项的简短说明。
    -W lint or --lint
    打印不能向传统unix平台移植的结构的警告。
    -W lint-old or --lint-old
    打印关于不能向传统unix平台移植的结构的警告。
    -W posix
    打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。
    -W re-interval or --re-inerval
    允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
    -W source program-text or --source program-text
    使用program-text作为源代码,可与-f命令混用。
    -W version or --version
    打印bug报告信息的版本。

2、awk的执行流程

其执行过程和sed相似,在我们遇到复杂的语句时,可以离利用执行过程来理解

题目:passwd文件的第二行的第一列和第二列

[root@luffy-001 oldboy]# awk -F ':' 'NR==2{print $1,$2}' /etc/passwd
bin x

awk   参数   ‘模式{动作}’    文件

awk   参数    ‘条件(找谁){干啥}’   文件

awk执行过程简图

3、模式匹配:模式与动作

怎么找到这一行,然后做点什么

通过正则表达式作为模式

创建测试环境

mkdir -p /server/files/
cat >>/server/files/reg.txt<<EOF
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
Meng  Feixue    80042789   :250:60:50
Wu    Waiwai    70271111   :250:80:75
Liu   Bingbing  41117483   :250:100:175
Wang  Xiaoai    3515064655 :50:95:135
Zi    Gege      1986787350 :250:168:200
Li    Youjiu    918391635  :175:75:300
Lao   Nanhai    918391635  :250:100:175
EOF

找出包含数字1的行

[root@luffy-001 files]# sed -n '/1/p' reg.txt 
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
Wu    Waiwai    70271111   :250:80:75
Liu   Bingbing  41117483   :250:100:175
Wang  Xiaoai    3515064655 :50:95:135
Zi    Gege      1986787350 :250:168:200
Li    Youjiu    918391635  :175:75:300
Lao   Nanhai    918391635  :250:100:175
[root@luffy-001 files]# awk '/1/' reg.txt 
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
Wu    Waiwai    70271111   :250:80:75
Liu   Bingbing  41117483   :250:100:175
Wang  Xiaoai    3515064655 :50:95:135
Zi    Gege      1986787350 :250:168:200
Li    Youjiu    918391635  :175:75:300
Lao   Nanhai    918391635  :250:100:175

awk支持的正则表达式

字符 功能
+ 指定如果一个或多个字符或扩展正则表达式的具体值(在 +(加号)前)在这个字符串中,则字符串匹配。命令行:

awk '/smith+ern/' testfile

将包含字符 smit,后跟一个或多个 h 字符,并以字符 ern 结束的字符串的任何记录打印至标准输出。此示例中的输出是:

smithern, harry smithhern, anne

? 指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:

awk '/smith?/' testfile

将包含字符 smit,后跟零个或一个 h 字符的实例的所有记录打印至标准输出。此示例中的输出是:

smith, alan smithern, harry smithhern, anne smitters, alexis

| 指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:

awk '/allen | alan /' testfile

将包含字符串 allenalan 的所有记录打印至标准输出。此示例中的输出是:

smiley, allen smith, alan

( ) 在正则表达式中将字符串组合在一起。命令行:

awk '/a(ll)?(nn)?e/' testfile

将具有字符串 aealleanneallnne 的所有记录打印至标准输出。此示例中的输出是:

smiley, allen smithhern, anne

{m} 指定如果正好有 m 个模式的具体值位于字符串中,则字符串匹配。命令行:

awk '/l{2}/' testfile

打印至标准输出

smiley, allen

{m,} 指定如果至少 m 个模式的具体值在字符串中,则字符串匹配。命令行:

awk '/t{2,}/' testfile

打印至标准输出:

smitters, alexis

{m, n} 指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m <= n),则字符串匹配。命令行:

awk '/er{1, 2}/' testfile

打印至标准输出:

smithern, harry smithern, anne smitters, alexis

[String] 指定正则表达式与方括号内 String 变量指定的任何字符匹配。命令行:

awk '/sm[a-h]/' testfile

将具有 sm 后跟以字母顺序从 ah 排列的任何字符的所有记录打印至标准输出。此示例的输出是:

smawley, andy

[^ String] 在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:

awk '/sm[^a-h]/' testfile

打印至标准输出:

smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis

~,!~ 表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:

awk '$1 ~ /n/' testfile

将第一个字段包含字符 n 的所有记录打印至标准输出。此示例中的输出是:

smithern, harry smithhern, anne

^ 指定字段或记录的开头。命令行:

awk '$2 ~ /^h/' testfile

将把字符 h 作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是:

smithern, harry

$ 指定字段或记录的末尾。命令行:

awk '$2 ~ /y$/' testfile

将把字符 y 作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是:

smawley, andy smithern, harry

. (句号) 表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:

awk '/a..e/' testfile

将具有以两个字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:

smawley, andy smiley, allen smithhern, anne

*(星号) 表示零个或更多的任意字符。命令行:

awk '/a.*e/' testfile

将具有以零个或更多字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:

smawley, andy smiley, allen smithhern, anne smitters, alexis

\ (反斜杠) 转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:

/a\/\//

将与模式 a // 匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。

 

题目:显示xiaoyu的姓氏和ID号码

[root@luffy-001 files]# awk '/Xiaoyu/' reg.txt 
Zhang Xiaoyu    390320151  :155:90:201
[root@luffy-001 files]# awk '/Xiaoyu/{print $1,$2,$3}' reg.txt 相当于$0~,$0 在awk中表示这一行,整行记录
Zhang Xiaoyu 390320151
[root@luffy-001 files]# awk '$2~/Xiaoyu/{print $1,$2,$3}' reg.txt   波浪线表示包含,第二列包含xiaoyu的行 的第一列,第二列,第三列
Zhang Xiaoyu 390320151

题目:显示所有以41开头的ID号码的人的全名和ID号码

[root@luffy-001 files]# awk '$3~/^41/{print $1,$2,$3}' reg.txt 
Zhang Dandan 41117397
Liu Bingbing 41117483

题目:显示所有ID号码最后一位数字是1或5的人的全名

[root@luffy-001 files]# awk '$3~/[15]$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai
[root@luffy-001 files]# awk '$3~/(1|5)$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

题目:显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135

gsub的用法:

gsub(/目标/,"替换为什么",第几列)
gsub(/目标/,"替换为什么") == gsub(/目标/,"替换为什么",$0)

[root@luffy-001 files]# sed 's#:#$#g' reg.txt 
Zhang Dandan    41117397   $250$100$175
Zhang Xiaoyu    390320151  $155$90$201
Meng  Feixue    80042789   $250$60$50
Wu    Waiwai    70271111   $250$80$75
Liu   Bingbing  41117483   $250$100$175
Wang  Xiaoai    3515064655 $50$95$135
Zi    Gege      1986787350 $250$168$200
Li    Youjiu    918391635  $175$75$300
Lao   Nanhai    918391635  $250$100$175
[root@luffy-001 files]# awk '{gsub(/:/,'$',$4);print}' reg.txt 
awk: {gsub(/:/,,$4);print}
awk:           ^ syntax error
awk: fatal: 0 is invalid as number of arguments for gsub
[root@luffy-001 files]# awk '{gsub(/:/,"$",$4);print}' reg.txt 
Zhang Dandan 41117397 $250$100$175
Zhang Xiaoyu 390320151 $155$90$201
Meng Feixue 80042789 $250$60$50
Wu Waiwai 70271111 $250$80$75
Liu Bingbing 41117483 $250$100$175
Wang Xiaoai 3515064655 $50$95$135
Zi Gege 1986787350 $250$168$200
Li Youjiu 918391635 $175$75$300
Lao Nanhai 918391635 $250$100$175

题目答案:

[root@luffy-001 files]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$4);print}' reg.txt 
Zhang Xiaoyu 390320151 $155$90$201

特殊模式:BEGIN 和END

BEGIN{} BEGIN里面的内容,会在awk读取文件内容之前运行。
测试,计算。

END{}*** END{}里面的内容,会在awk读取完文件的最后一行之后运行。
用来显示最终结果。
先计算,END显示结果。

[root@luffy-001 files]# awk 'BEGIN{print "this is kt"} {print NR,$0}' reg.txt 
this is kt
1 Zhang Dandan    41117397   :250:100:175
2 Zhang Xiaoyu    390320151  :155:90:201
3 Meng  Feixue    80042789   :250:60:50
4 Wu    Waiwai    70271111   :250:80:75
5 Liu   Bingbing  41117483   :250:100:175
6 Wang  Xiaoai    3515064655 :50:95:135
7 Zi    Gege      1986787350 :250:168:200
8 Li    Youjiu    918391635  :175:75:300
9 Lao   Nanhai    918391635  :250:100:175
[root@luffy-001 files]# awk 'BEGIN{print "this is kt"} END{print "this is kb"} {print NR,$0}' reg.txt 
this is kt
1 Zhang Dandan    41117397   :250:100:175
2 Zhang Xiaoyu    390320151  :155:90:201
3 Meng  Feixue    80042789   :250:60:50
4 Wu    Waiwai    70271111   :250:80:75
5 Liu   Bingbing  41117483   :250:100:175
6 Wang  Xiaoai    3515064655 :50:95:135
7 Zi    Gege      1986787350 :250:168:200
8 Li    Youjiu    918391635  :175:75:300
9 Lao   Nanhai    918391635  :250:100:175
this is kb

题目:统计/etc/services文件里面的空行数量

[root@luffy-001 files]# awk '/^$/{print NR}' /etc/services 
22
266
299
320
326
393
461
474
479
486
494
506
512
518
583
584
[root@luffy-001 files]# awk '/^$/{i=i+1;print i}' /etc/services 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@luffy-001 files]# awk '/^$/{i=i+1} END{print i}' /etc/services 
16

统计出现多少次 计数
i=i+1 ===> i++

常见用法

##用法一:
awk '{[pattern] action}' {filenames}   # 行匹配语句 awk '' 只能用单引号
##用法二:
awk -F  #-F相当于内置变量FS, 指定分割字符
##用法三:
awk -v  # 设置变量
##用法四:
awk -f {awk脚本} {文件名}

4、awk数组:统计与计算

数组怎么使用?

举个例子:

[root@luffy-001 files]# awk 'BEGIN{h[110]="张三";h[114]="XXOO";print h[110],h[114]}'
张三 XXOO

运算符

运算符                         描述
= += -= *= /= %= ^= **=       赋值
?:                           C条件表达式
||                           逻辑或
&&                            逻辑与
~ ~!                         匹配正则表达式和不匹配正则表达式
< <= > >= != ==               关系运算符
空格                           连接
+ -                           加,减
* / %                       乘,除与求余
+ - !                       一元加,减和逻辑非
^ ***                        求幂
++ --                     增加或减少,作为前缀或后缀
$                              字段引用
in                               数组成员

题目:处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html

## 分割后查看,独有的前缀为标记
[root@luffy-001 files]# awk -F '[/.]+' '{print $2}' url.txt 
www
www
post
mp3
www
post
## 使用h[$2]建立数组,并自加,打印出其中一个
[root@luffy-001 files]# awk -F '[/.]+' '{h[$2]++;print h["www"]}' url.txt 
1
2
2
2
3
3
## 答应所有的结果,只是当种类多了之后,没法操作
[root@luffy-001 files]# awk -F '[/.]+' '{h[$2]++} END{print h["www"],h["post"],h["mp3"]}' url.txt 
3 2 1
## awk独有的循环的功能
[root@luffy-001 files]# awk -F '[/.]+' '{h[$2]++} END{for(pol in h) print pol,h[pol]}' url.txt 
www 3
mp3 1
post 2

题目:统计access.log文件中每个ip地址出现的次数
题目:secure系统日志分析练习
谁在破解你的密码(Failed password 每个ip地址出现的次数)
分析系统的每个用户被破解的次数

## 统计IP登录次数
[root@luffy-001 log]# awk '$0~/Accepted/{h[$11]++}END{for(por in h) print por,h[por]}' secure
10.0.0.1 3
## 统计每个用户被破解的次数
[root@luffy-001 log]# awk '$0~/FAILED LOGIN/{h[$12]++}END{for(por in h) print por,h[por]}' secure
rot, 1
## 统计谁在破解你的密码(Failed password 每个ip地址出现的次数)
[root@luffy-001 log]# awk -F "[()]" '/FAILED/{h[$2]++}END{for(pol in h) print pol, h[pol]}' secure
null 1

猜你喜欢

转载自www.cnblogs.com/yxiaodao/p/10399780.html