awk基本用法
awk [-F"分隔符" | -v var=value ] 'BEGIN{action}/pattern/{action}END{action}' file ...
awk工作原理
- 第一步
- 执行BEGIN{action;… }语句块中的语句
- BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,
比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
- 第二步
- 从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕
- pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
- 第三步
- 当读至输入流末尾时,执行END{action;…}语句块
- END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
选项
- -F "分隔符" # 分隔符可以使用正则表达式
df | awk -F " +|%" '{print $1,$5}'
- -v var=value 变量赋值
awk变量
内置变量
- FS:输入字段分隔符,默认为空白符
awk -v FS=':' '{print $1,FS,$3}' /etc/passwd
- OFS:输出字段分隔符,默认为空白符
awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd
- RS:输入记录分隔符,指定输入时的换行符
awk -v RS='' '{print}' /etc/passwd
- ORS: 输出记录分隔符,输出时用指定符号代替换行符
awk -v RS='' -v ORS='###' '{print}' /etc/fstab
- NF:字段数量
awk -F: '{print NF}' /etc/fstab
awk -F: '{print $(NF-1)}' /etc/passwd
- NR:记录号
awk END‘{print NR}’ /etc/fstab
awk END'{print NR}' /etc/fstab
- FNR: 各文件分别计数,记录号
awk '{print FNR}' /etc/fstab /etc/inittab
- FILENAME:当前文件名
awk '{print FILENAME}' /etc/fstab
- ARGC: 命令行参数的个数
awk '{print ARGC}' /etc/fstab /etc/inittab
awk 'BEGIN {print ARGC}' /etc/fstab /etc/inittab
- ARGV: 数组,保存的是命令行所给定的各参数
awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab
awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab
自定义变量
- -v var=value
awk -v test='hello gawk' '{print test}' /etc/fstab
- 在program中直接定义
awk 'BEGIN{test="hello gaswk";print test}'
awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
Pattern
awk PATTERN
根据pattern过滤匹配的行 awk '/pattern/{}'
- /regular expression/
- relational expression
- line ranges /pat1/,/pat2/
Action
- Expression:算术,比较表达式
- control statement: if, while
- compound statements:组合语句
- input statements
- output statements: print等
awk格式化 printf
格式
printf "FORMAT", item1, item2, ...
Format | comments |
---|---|
格式符 | |
%c | 显示字符的ASCII码 |
%d, %i | 显示十进制整数 |
%e,%E | 显示科学计数法数值 |
%f | 显示浮点数 |
%g, %G | 以科学计数法或浮点形式显示数值 |
%s | 显示字符串 |
%u | 无符号整数 |
%% | 显示% |
修饰符 | |
#[.#] | 第一个数字控制显示宽度;第二各数字表示小数点后精度 |
- | 左对齐 |
+ | 显示数值的正负号 |
[root@test1_c1 data]#awk -F: '{printf "%s", $1}' /etc/passwd
rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-networkdbuspolkitdlibstoragemgmtabrtrpcsshdpostfixchronyntptcpdumpapachesaslauthwangxiangmysqlxingabcuser1user2user3user4user5user6user7user8user9user10
[root@test1_c1 data]#awk -F: '{printf "%s\n", $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
[root@test1_c1 data]#awk -F: '{printf "%-20s %10d\n",$1,$2}' /etc/passwd
root 0
bin 0
daemon 0
adm 0
lp 0
sync 0
shutdown 0
halt 0
mail 0
operator 0
games 0
[root@test1_c1 data]#awk -F: '{printf "Username: %s,UID:%d\n",$1,$3}' /etc/passwd
Username: root,UID:0
Username: bin,UID:1
Username: daemon,UID:2
Username: adm,UID:3
Username: lp,UID:4
Username: sync,UID:5
Username: shutdown,UID:6
Username: halt,UID:7
Username: mail,UID:8
Username: operator,UID:11
Username: games,UID:12
[root@test1_c1 data]#awk -F: '{printf "Username:%15s,UID:%d\n",$1,$3}' /etc/passwd
Username: root,UID:0
Username: bin,UID:1
Username: daemon,UID:2
Username: adm,UID:3
Username: lp,UID:4
Username: sync,UID:5
Username: shutdown,UID:6
Username: halt,UID:7
Username: mail,UID:8
Username: operator,UID:11
Username: games,UID:12
[root@test1_c1 data]#awk -F: '{printf "Username:%-15s, UID:%d\n",$1,$3}' /etc/passwd
Username:root , UID:0
Username:bin , UID:1
Username:daemon , UID:2
Username:adm , UID:3
Username:lp , UID:4
Username:sync , UID:5
Username:shutdown , UID:6
Username:halt , UID:7
Username:mail , UID:8
Username:operator , UID:11
Username:games , UID:12
awk操作符
算术操作符
- x+y, x-y,x*y,x/y,x^y,x%y
2 - x : 转换为负数 - +x:将字符串转换为数值
字符串操作符
赋值操作符
=,+=,-=,*=,/=,%=,^=,++,--
[root@test1_c1 scripts]#awk 'BEGIN{i=0;print ++i,i}'
1 1
[root@test1_c1 scripts]#awk 'BEGIN{i=0;print i++,i}'
0 1
比较操作符
==,!=,>,>=,<,<=
模式匹配符
- ~: 左边是否和右边匹配,包含
- !~:是否不匹配
逻辑操作符
&&,||,!
awk -F: '$3>=0 && $3<=100{print $1}' /etc/passwd
awk -F: '$3==0 || $3>=1000{print $1}' /etc/passwd
awk -F: '!($3==0){print $1}' /etc/passwd
awk -F: '!($3>=500){print $3}' /etc/passwd
条件表达式
selector?if-true-expression:if-false-expresiion
awk -F: '{$3>=1000?usertype="Common User":usertype="Sysuser"; \
printf "%15s:%-s\n",$1,usertype}' /etc/passwd
awk控制语句
组合语句
{statements1;statements2;...}
条件
对awk取得的整行或某个字段做条件判断
- if(condition) {statements;...}
- if(condition) {statements;...} eles {statements;...}
- switch(expression){case VALUE1 or /REGEXP/: statement1; /
case VALUE2 or /REGEXP2: statement2; /
......
default: statemens}
df | awk -F " +|%" '/^\/dev\//{if($5>10){printf "Disk %s utility %d above 80%\n",$1,$5}else{printf "Disk %s is safe\n", $1}}'
循环
对一行内多个字段逐一类似处理
对数值各元素逐一处理
- while(condition) {statements; ...}
- do {statements; ...} while(condition)
- for(expr1;expr2;expr3) {statements; ...}
- for(var in array) {for-body}
- break
- continue
- next
提前结束对本行处理而直接进入下一行处理
awk '/linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /boot/grub2/grub.cfg
awk -v sum=0 'BEGIN{i=1;while(i<=100){sum+=i;i++};print sum}'
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i}print "sum="sum}'
[root@test1_c1 scripts]#time seq -s+ 100000 | bc
5000050000
real 0m0.040s
user 0m0.039s
sys 0m0.003s
[root@test1_c1 scripts]#time awk -v sum=0 'BEGIN{i=1;while(i<=100000){sum+=i;i++};print sum}'
5000050000
real 0m0.011s
user 0m0.010s
sys 0m0.001s
[root@test1_c1 scripts]#time awk 'BEGIN{sum=0;for(i=1;i<=100000;i++){sum+=i}print "sum="sum}'
sum=5000050000
real 0m0.010s
user 0m0.008s
sys 0m0.002s
数组
关联数组:array[index-expression]
index-expression
- 可以使用任意字符串;字符串用双引号括起来
- 如果数组元素不存在,引用其时,awk自动创建此元素,并初始化为空串
- 遍历数组
for(var in array) {for-body} # var为数组下标 - 删除数组元素和数组
- delete array[index]
- delete array
# 去重打印
awk '!a[$0]++' data.txt
#统计每个ip出现的此时
awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access_log
ss -nat | awk '! /^State/{state[$1]++}END{for(i in state){print i,state[i]}}'
函数
自带函数
- 数值处理 rand()返回0和1之间一个随机数
awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
- 字符串处理
- length([s])
- sub(r,s,[t]): 对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s
- gsub(r,s,[t]): 对t字符串搜索r表示模式匹配的内容,并全部替换为s
- split(s,array,[r]): 以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组,第一个索引为1,第二个索引为2
自定义函数
function name (parameter1, parameter2, ...) {
statements
return expression
}
调用系统命令 system
- 空格是awk中的字符串连接符,除了awk中的变量外其它一律用""
awk脚本
向awk脚本传递参数
awkfile var=value var2=value2.... inputfile