awk 简介
awk是处理文本文件的一个应用程序,几乎所有 Linux 系统都自带这个程序。
原理:
它依次处理文件的每一行,并读取里面的每一个字段。
使用场景:
对于日志、CSV 那样的每行格式相同的文本文件,awk可能是最方便的工具。
awk其实不仅仅是工具软件,还是一种编程语言。不过,本文只介绍它的命令行用法。
基本用法
# 格式
$ awk [flags] '[range1] {动作1} [range2] {动作2} ...'' 文件名
说明:
范围:表示动作的执行范围、比如BEGIN、END、模式匹配/PATTERN/, 条件等;
动作:一般用{}包含;
注:使用单引号''来包含范围以及动作;
# 示例
$ awk '{print $0}' demo.txt
上面示例中,demo.txt是awk所要处理的文本文件。
前面单引号内部有一个大括号,里面就是每一行的处理动作print $0。
其中,print是打印命令,$0代表当前行,
因此上面命令的执行结果,就是把每一行原样打印出来。
$ echo ‘this is a test’ | awk ‘{print $0}’
this is a test
上面代码中,print $0就是把标准输入this is a test,重新打印了一遍。
awk会根据空格和制表符,将每一行分成若干字段,
依次用$1、$2、$3代表第一个字段、第二个字段、第三个字段等等。
$ echo ‘this is a test’ | awk ‘{print $3}’
a
参数
-F: file seperator; 指定域分隔符;
为了便于举例,我们把/etc/passwd文件保存成demo.txt。
root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
用-F参数指定分隔符为冒号。然后,才能提取到它的第一个字段。
$ awk -F ':' '{ print $1 }' demo.txt
root
daemon
bin
sys
sync
变量
字段
$ + 数字表示某个字段
$0: 整行;
$1: 第一个字段;
$2: 第二个字段;
特殊字段
NF
变量NF(number of filed)表示当前行有多少个字段,
因此$NF就代表最后一个字段。$(NF-1)代表倒数第二个字段。
$ awk -F ':' '{print $1, $(NF-1)}' demo.txt
root /root
daemon /usr/sbin
bin /bin
sys /dev
sync /bin
上面代码中,print命令里面的逗号,表示输出的时候,两个部分之间使用空格分隔。
NR
变量NR(number of record)表示当前处理的是第几行。
$ awk -F ':' '{print NR ") " $1}' demo.txt
1) root
2) daemon
3) bin
4) sys
5) sync
其他变量
FILENAME:当前文件名,在一次性处理多个文件时非常有用;
FS:字段分隔符(field seperator),默认是空格和制表符。
RS:行分隔符(record seperator),用于分割每一行,默认是换行符。
OFS:输出字段的分隔符(output field seperator),用于打印时分隔字段,默认为空格。
ORS:输出记录的分隔符(output record seperator),用于打印时分隔记录,默认为换行符。
OFMT:数字输出的格式(output format),默认为%.6g。
FS
下面的两个命令是等价的 。
awk -F ':' '{print $3}' file
awk 'BEGIN{FS=":"}{print $3}' file
如果你的文件既有用,分隔的,也有用:分割的,
FS甚至可以指定多个分隔符同时起作用。
FS="[,:|]"
NF
NF 列数。非常有用,比如,过滤一些列数不满足条件的内容。
awk -F, '{if(NF==3){print}}' file
NR
NR 行号,例如,下面两个命令是等价的。
cat -n file
awk '{print NR,$0}' file
OFS
OFS 指定输出内容的分割符,列数非常多的时候,简化操作。相似命令:
awk -F ':' '{print $1,"-",$2,"-",$4}' file
awk 'BEGIN{FS=":";OFS="-"}{print $1,$2,$4}' file
函数
awk还提供了一些内置函数,方便对原始数据的处理。
函数toupper()
函数toupper()用于将字符转为大写。
$ awk -F ':' '{ print toupper($1) }' demo.txt
ROOT
DAEMON
BIN
SYS
SYNC
其他函数
tolower():字符转为小写。
length():返回字符串长度。
substr():返回子字符串。
sin():正弦。
cos():余弦。
sqrt():平方根。
rand():随机数。
更多函数参考:awk官方内置函数
条件
awk允许指定输出条件,只输出符合条件的行。
输出条件要写在动作的前面, 如下所示:
$ awk ‘条件 {动作}’ 文件名
$ awk -F ':' '/usr/ {print $1}' demo.txt
root
daemon
bin
sys
上面代码中,print命令前面是一个正则表达式,只输出包含usr的行。
# 输出奇数行
$ awk -F ':' 'NR % 2 == 1 {print $1}' demo.txt
root
bin
sync
# 输出第三行以后的行
$ awk -F ':' 'NR >3 {print $1}' demo.txt
sys
sync
输出第一个字段等于指定值的行:
$ awk -F ':' '$1 == "root" {print $1}' demo.txt
root
$ awk -F ':' '$1 == "root" || $1 == "bin" {print $1}' demo.txt
root
bin
if 语句
awk提供了if结构,用于编写复杂的条件, 比如可以 if…else 来进行复杂的处理;
$ awk -F ':' '{if ($1 > "m") print $1}' demo.txt
root
sys
sync
输出第一个字段的第一个字符大于m的行。
$ awk -F ':' '{if ($1 > "m") print $1; else print "---"}' demo.txt
root
---
---
sys
sync
范例
netstat统计输出
采用awk统计netstat命令的一些网络状态,netstat的输出类似于:
第6列,标明了网络连接所处于的网络状态, 统计每个状态的个数;
netstat -ant |
awk ' \
BEGIN{print "State","Count" } \
/^tcp/ \
{ rt[$6]++ } \
END{ for(i in rt){print i,rt[i]} }'
上面的rt[$6]++,就已经默认定义了一个叫做rt的hash(array?),
里面的key是网络状态,而value是可以进行运算的(+-*/%)。
输出结果为:
State Count
LAST_ACK 1
LISTEN 64
CLOSE_WAIT 43
ESTABLISHED 719
SYN_SENT 5
TIME_WAIT 146
分析
-
BEGIN 开头部分,可选的。
用来设置一些参数,输出一些表头,定义一些变量等。
上面的命令仅打印了一行信息而已。 -
END 结尾部分,可选的。
用来计算一些汇总逻辑,或者输出这些内容。
上面的命令,使用简单的for循环,输出了数组rt中的内容。 -
Pattern 匹配部分,依然可选。
用来匹配一些需要处理的行。上
面的命令,只匹配tcp开头的行,其他的不进入处理。 -
Action 模块。
主要逻辑体,按行处理,统计打印,都可以。
参考
http://www.ruanyifeng.com/blog/2018/11/awk.html
https://mp.weixin.qq.com/s?__biz=MzA4MTc4NTUxNQ==&mid=2650519843&idx=1&sn=fe4a5c405a35b42a850054eb4283ff40&chksm=8780bee7b0f737f194d356c155b67d19be574454adcb8ce0d16c84e6246a718c9cf29c223512&scene=21#wechat_redirect