如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里
awk的工作模式其实就类似sed一样,逐行处理行数据
语法格式
stdout | awk [option] 'BEGIN{}pattern{comands}END{}'
,通过管道对标准输出进行处理awk [option] 'BEGIN{}pattern{comands}END{}' files
, 对文件进行处理重要概念
BEGIN中的命令是在遍历文件前执行的,END中的命令是在处理文件所有数据后才执行的,pattern中的命令就是对每个匹配行进行处理
BEGIN{}
pattern
{commands}
END{}
'{print NF}'
-F fs
awk -F "-" '{print $0}' file
-v var=value
-f scripfile
内置变量 | 含义 | 备注 |
---|---|---|
$0 |
整行内容 | |
$1 -$n |
当前行的第1-n个字段 | 比如hello world,$1是hello, $2是world |
NF |
当前行的字段个数,也就是有多少列 | Number Field |
NR |
当前行的行号,从1开始计数 | Number Row |
FNR |
多文件处理时,每个文件行号单独计数,都是从0开始 | File Number Row |
FS |
输入字段分隔符,不指定就默认以空格或tab键分割 | 输入给awk的内容以FS作为在字段分隔 |
RS |
输入行分隔符,默认回车换行 | |
OFS |
输出字段分割符,默认为空格 | awk输出的内容的字段以OFS作为字符分割 |
ORS |
输出行分割符,默认为回车换行 | |
FILENAME |
输入行分隔符,默认回车换行 | |
ARGC |
命令行参数个数 | awk ‘BEGIN{print ARGC}’ cpu 输出2个参数,awk是一个,cpu文件名也是一个 |
ARGV |
命令行参数数组 |
{commands}
默认为空是,输出行的完整信息,等价print $0
NR变量
去控制行号,同时pattern不仅局限于使用正则,同时支持运算符号判断,比如大于,小于,等于,不等于等…格式符 | 含义 | 备注 |
---|---|---|
%s |
打印字符串 | printf "%20s" helloworld 右对齐20字符固长输出 |
%d |
打印十进制数 | |
%f |
打印浮点数 | printf "%0.3f" 123 |
%x |
打印十六进制数 | printf "%#x" 123 (输出带0x),printf "%x" 123 |
%o |
打印八进制数 | |
%e |
打印科学计数法 | |
%c |
打印字符的ASCII码 | |
- |
左对齐 | printf "%-20s" hello 左对齐,20固长的字符串输出 |
+ |
右对齐 | printf默认输出是右对齐 |
# |
打印字符的ASCII码 |
awk模式匹配有两种用法。第一种是RegExp
, 按照正则表达式匹配;第二种是关系运算
,按照关系运算匹配
RegExp
/root/
/root/,/10/
关系运算
<
,>
,<=
,>=
,==
,!=
awk '$3<50{print $0}'
awk '$7=="hello"{print $0}'
awk 'NR==10'{print $0} file.txt
~
,!~
awk '$3~/[0-9]{3,}{print $0}/'
||
,&&
,!
awk '/java/||/python/{print $0}'
awk '$3>50 || $8<100{print $0}'
格式符 | 含义 | 备注 |
---|---|---|
+ |
加 | |
- |
减 | |
* |
乘 | |
/ |
除 | |
% |
模 | |
^或** |
乘方 | |
++x |
就是语言中的i++ | |
x++ |
就是语言中的i++ |
BEGIN{num = 1;num++;} {num++;}END{print num}
, BEGIN代码块初始化num变量,{commands}每匹配一个行,num++, 匹配文件结束后执行END代码块的print num, 输出num变量,这样我们就知道了awk总共匹配了多少行条件语句
if(条件){
...
} else if (条件){
...
} else {
...
}
循环语句
while(条件表达式){
...
}
do{
...
}while(条件表达式)
for(i = 0; i<10;i++){
...
}
跟c的区别就是,awk的变量不需要声明
函数名 | 解释 | 函数返回值 | 备注 |
---|---|---|---|
length(str) |
计算字符串长度 | 整数长度值 | |
index(str1,str2) |
在str1中查找str2的位置 | 返回值为位置索引,从1开始计数 | |
tolower(str) |
字符串全部转为小写 | 小写字符串 | |
toupper(str) |
字符串全部转为大写 | 大写字符串 | |
substr(str,m,n) |
从str的m个字符开始,窃取n位 | 字符串子串 | |
split(str,arr,fs) |
按照fs分割字符串,保存到arr数组中 | 数组的长度 | |
match(str,RE) |
在str中按照RE查找,返回位置 | 索引位置 | |
sub(RE,RepStr,str) |
从str搜索符合RE的子串,将其替换成RepStr, 替换一个 | 替换个数 | |
gsub(str,arr,fs) |
从str搜索符合RE的子串,将其替换成RepStr, 替换全部 | 替换个数 | RE是正则 |
awk 'BEGIN{str="I love you"; index=index(str,"love");print index}'
awk 'BEGIN{str="I love you"; index=match(str,"love");print index}'
awk的数组的使用和shell脚本中数组的使用是有些不同的,这个要注意
Shell脚本下数组的使用
array=("Jerry" "Tom" "Li" "Allen")
echo ${array[2]}
echo ${#array[@]}
,求个数基本都是#xx, 比如字符串的长度#strecho{#array[1]}
array[3] = "Mike"
unset array[2]
, 要删除整个数组则是unset array[@]
, 其实就是清空遍历echo ${array[@]:1:3}
${array[@]/old/new}
, 使用new替换一个old${array[@]//old/new}
, 使用new替换所有oldfor i in array
do
echo $i
done
awk脚本下数组的使用
# PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,COMMAND
165,lwj,20,0,16920,3564,3452,S,0.0,0.0,0:00.30,-bash,
266,lwj,20,0,17016,3656,3344,S,0.0,0.0,0:00.36,-bash,
321,lwj,20,0,27888,6492,3304,S,0.0,0.0,0:00.20,vim,h,
364,lwj,20,0,16884,3444,3372,S,0.0,0.0,0:00.07,-bash,
375,lwj,20,0,14860,1148,964,S,0.0,0.0,0:00.03,sed,-n,/lwj/w,cpua,
awk 'BEGIN{FS=","}{print $1,$2,$3}' cpu
, 修改字段分隔符FS为逗号,
,不再是空格或tab键, 输出每行的第1,2,3个单词(要注意,逗号用双引号括住,而不是单引号)165 lwj 20
266 lwj 20
321 lwj 20
364 lwj 20
375 lwj 20
awk 'BEGIN{FS=",";OFS="-"}{print $0}' cpu
, 输入字符分隔修改为",“逗号,输出字符分隔修改为”-",输出每行的第1,2,3个单词(要注意print $1,$2,$3字段之间要用","号分隔,如果没有逗号,使用空格,那么输出分隔符会失效)165-lwj-20
266-lwj-20
321-lwj-20
364-lwj-20
375-lwj-20
# PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,COMMAND
165,lwj,20,0,16920,3564,3452,S,0.0,0.0,0:00.30,-bash,
266,lwj,20,0,17016,3656,3344,S,0.0,0.0,0:00.36,-bash,
321,lwj,20,0,27888,6492,3304,S,0.0,0.0,0:00.20,vim,h,
364,lwj,20,0,16884,3444,3372,S,0.0,0.0,0:00.07,-bash,
375,lwj,20,0,14860,1148,964,S,0.0,0.0,0:00.03,sed,-n,/lwj/w,cpua,
awk 'BEGIN{FS=","}{printf "%-20s %-20s",$1,$2}' cpu
格式化输出cpu的第一和第二列字段,格式化为输出字符串,每一列固定20个字符串,左对齐方式输出,字段之间2个空格长度隔开165 lwj
266 lwj
321 lwj
364 lwj
375 lwj
awk 'BEGIN{FS=","}{printf "%+20s %+20s",$1,$2}' cpu
, 右对齐 165 lwj
266 lwj
321 lwj
364 lwj
375 lwj
top -H -n 1 >> cpu
将top的信息追加到cpu文件中top - 20:42:12 up 40 days, 9:46, 1 user, load average: 0.00, 0.07, 0.04
Threads: 284 total, 1 running, 245 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.1 us, 1.0 sy, 0.0 ni, 97.4 id, 0.5 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1877536 total, 157380 free, 822956 used, 897200 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 856424 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6939 ubuntu 20 0 43556 4076 3296 R 5.9 0.2 0:00.01 top
1 root 20 0 225520 7796 5204 S 0.0 0.4 1:46.62 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.20 kthreadd
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
7 root 20 0 0 0 0 S 0.0 0.0 2:09.87 ksoftirqd/0
8 root 20 0 0 0 0 I 0.0 0.0 21:46.47 rcu_sched
9 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_bh
10 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
11 root rt 0 0 0 0 S 0.0 0.0 0:06.17 watchdog/0
12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0
13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
14 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 netns
15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_kthre
16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kauditd
17 root 20 0 0 0 0 S 0.0 0.0 0:01.32 khungtaskd
18 root 20 0 0 0 0 S 0.0 0.0 0:00.00 oom_reaper
19 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 writeback
20 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kcompactd0
21 root 25 5 0 0 0 S 0.0 0.0 0:00.00 ksmd
22 root 39 19 0 0 0 S 0.0 0.0 0:12.74 khugepaged
23 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 crypto
24 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kintegrityd
awk '/PID/,/END/{if (NR>7){printf "%-8s %-8s\n",NR,$0}}' cpu
8 9061 ubuntu 20 0 43556 4092 3312 R 6.2 0.2 0:00.01 top
9 1 root 20 0 225520 7796 5204 S 0.0 0.4 1:46.64 systemd
10 2 root 20 0 0 0 0 S 0.0 0.0 0:00.20 kthreadd
11 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H
12 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
13 7 root 20 0 0 0 0 S 0.0 0.0 2:09.91 ksoftirqd/0
14 8 root 20 0 0 0 0 I 0.0 0.0 21:46.89 rcu_sched
15 9 root 20 0 0 0 0 I 0.0 0.0 0:00.00 rcu_bh
16 10 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
17 11 root rt 0 0 0 0 S 0.0 0.0 0:06.17 watchdog/0
18 12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0
19 13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
20 14 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 netns
21 15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_kthre
22 16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kauditd
23 17 root 20 0 0 0 0 S 0.0 0.0 0:01.32 khungtaskd
24 18 root 20 0 0 0 0 S 0.0 0.0 0:00.00 oom_reaper
25 19 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 writeback
26 20 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kcompactd0
27 21 root 25 5 0 0 0 S 0.0 0.0 0:00.00 ksmd
28 22 root 39 19 0 0 0 S 0.0 0.0 0:12.74 khugepaged
29 23 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 crypto
30 24 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kintegrityd
Jerry 80 90 78 56
Tom 45 65 89 12
Allen 89 96 95 87
Li 45 89 75 63
awk '{total=$2+$3+$4+$5;avg=total/4;printf "%-10s %-10 0.2f\n",$1,avg}' student
Jerry 76.00
Tom 52.75
Allen 91.75
Li 68.00
awk '{if($2>60) print $1,$2}' student
, 输出第一列成绩中合格的学生(大于60分)Jerry 80
Allen 89
awk -f cal.awk student
, 计算横向和纵向数据的总和# cak.awk
BEGIN{
printf "%-10s%-10s%-10s%-10s%-10s%-10s\n","Name","Chinese","Math","Enligsh","PC","Sum"
}
{
total=$2+$3+$4+$5;
for(i=2;i<=NF;i++){
sum=array[i];
array[i]=sum+$i;
}
printf "%-10s%-10d%-10d%-10d%-10d%-10d\n",$1,$2,$3,$4,$5,total
}
END{
printf "%-10s%-10d%-10d%-10d%-10d%-10d\n","",array[2],array[3],array[4],array[5],""
}
# output
Name Chinese Math Enligsh PC Sum
Jerry 80 90 78 56 304
Tom 45 65 89 12 211
Allen 89 96 95 87 367
Li 45 89 75 63 272
259 337 218 0 0