AWK 快速入门
变量名 | 解释 |
---|---|
$0 | 当前记录(这个变量中存放着整个行的内容) |
1 1~ 1 n | 当前记录的第n个字段,字段间由FS分隔 |
FS | 输入字段分隔符 默认是空格或Tab |
NF | 当前记录中的字段个数,就是有多少列 |
NR | 已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。 |
FNR | 当前记录数,与NR不同的是,这个值会是各个文件自己的行号 |
RS | 输入的记录分隔符, 默认为换行符 |
OFS | 输出字段分隔符, 默认也是空格 |
ORS | 输出的记录分隔符,默认为换行符 |
FILENAME | 当前输入文件的名字 |
命令的常用格式
awk [选项] 'BEGIN{开始语句} 模式{动作} END{结束语句}' [文件]
awk 'BEGIN{} {每行执行的action} END{}'
awk '{if(判断条件)每行执行的action}'
awk '判断条件 {action}' 文件路径
BEGIN{}是执行程序前只执行一次的代码。
END{}中是执行程序完成后只执行一次的代码。
模式和动作可以都存在,也可以二者选其一。如果省略模式,那么文件的所有行都执行该动作;如果省略动作,表示对符合条件的行执行默认的print动作。正因为可以二者选其一,所以一般用{}包裹动作,用于区分模式和动作。
输出指定列的数据
awk '{print $1, $4}' xxx.log
## 打印第一列和第四列,$0表示整个行
列的分割符默认是 空格和TAB。
自定义列分隔符
awk -F',' '{print $1, $4}' xxx.log ## 以,为分隔符
awk -F'26' '{print $1, $4}' xxx.log ## 以26为分隔符,输出两列数据,以空格分隔。
awk -F'26' '{print $1 $4}' xxx.log ## 以26为分隔符,输出两列数据,数据之间无分隔符(实际上就是一列)。
awk -F',' '{print $1,"+", $4}' xxx.log ##
## 打印第一列和第四列,$0表示整个行
利用[]同时指定多个分隔符
awk -F'[,.!;]' '{print $1, $4}' xxx.log
指定了四个分隔符‘,’ ‘.‘ ’!‘ ’;‘ 。 注意中括号里的每个单字符都是分隔符。
遗留问题:如何同时指定多个单字符和多字符为分隔符?
过滤
## xx.txt如下
unix 2 [ ] DGRAM 38472 /run/systemd/shutdownd
unix 6 [ ] DGRAM 9299 /run/systemd/journal/socket
unix 26 [ ] DGRAM 9301 /dev/log
unix 2 [ ] DGRAM 43073 /var/lib/samba
awk '$2 == 26' xx.txt
awk '$2 == 26 {print $0}' xx.txt
awk '{if($2==26)print($0)}' xx.txt ##
## 当第二个变量是26时, 输出整行,上述两行效果相同。
BEGIN 和 END
awk 'BEGIN{sum=1}{sum+=$1}END{print("sum = "sum)}' xx.txt
awk '{sum+=$1}END{print("sum = "sum)}' xx.txt
## 不加begin则sum默认初始化为0
if else
akw语言支持if else。
awk 'if() print(); else if () print(); else xxx' xxx.log
AWK脚本
$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
A = 0
E = 0
C = 0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
A +=$3
E +=$4
C +=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf " TOTAL:%10d %8d %8d \n", A, E, C
printf "AVERAGE:%10.2f %8.2f %8.2f\n", A/NR, E/NR, C/NR
}
> awk -f cal.awk score.txt
默认变量
NR
已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
awk 'NR!=1{print($1)}'
## 当不是第一行时执行action
以下三个变量没看懂
RS | 输入的记录分隔符, 默认为换行符 |
---|---|
OFS | 输出字段分隔符, 默认也是空格 |
ORS | 输出的记录分隔符,默认为换行符 |
字符串匹配
使用~进行字符串正则匹配
awk '$6 ~ /XXX/ || NR==1 {print NR,$4,$5,$6}' netstat.txt
##当第六个变量匹配到字符串XXX或着 当前是第一行,则打印...
##同时匹配多个字符串用 |
awk '$6 ~ /XXX|YYY/ || NR==1 {print NR,$4,$5,$6}' netstat.txt
## 取反
awk '$6 !~ /XXX/ || NR==1 {print NR,$4,$5,$6}' netstat.txt
参考:
gawk mannul
https://www.gnu.org/software/gawk/manual/gawk.html
coolshell
https://coolshell.cn/