一、awk基础语法(常用,其他不常用)
语法:
awk [选项] ‘条件{动作} 条件{动作}’ 文件名 ...
1、内置变量
变量名 | 描述 |
---|---|
FILENAME | 当前输入文件的名称 |
FNR | 当前输入文档的当前行号,尤其当有多个输入文档时有用 |
NR | 输入数据流的当前行号 |
$0 | 当前行的全部内容 |
$n | 当前行的第n个字段内容(n>1) |
NF | 当前记录(行)的字段(列)个数 |
FS | 字段分隔符,默认为空格或Tab制表符 |
OFS | 输出字段分隔符,默认为空格 |
ORS | 输出行分隔符,默认换行符为\n |
RS | 输入行分隔符,默认换行符为\n |
[root@www jiaofan]# free | awk '{print $2}' #<==打印第二列
used
995672
2097148
[root@www jiaofan]# free | awk '{print NR}' #<==输出行号
1
2
3
[root@www jiaofan]# free | awk '{print NF}' #<==输出每行的列数
6
7
4
[root@www jiaofan]# free | awk '{print $NF}' #<==打印最后一列
available
287716
2097148
[root@www jiaofan]# free | awk '{print $(NF-1)}' #<==打印倒数第二列
buff/cache
288292
0
[root@www jiaofan]# cat test1.txt #<==文件1
hello world!
other men live to eat,while I eat to live.
It is never too late to mend.
[root@www jiaofan]# cat test2.txt #<==文件2
biscuit:crisp:chichen
salt-jam:oil,suger
banana:lemon,pear--apple:grape
[root@www jiaofan]# awk '{print $2}' test1.txt #<==输出第一列
world!
men
is
[root@www jiaofan]# awk '{print $0}' test1.txt #<==输出每行的全部内容
hello world!
other men live to eat,while I eat to live.
It is never too late to mend.
[root@www jiaofan]# awk '{print}' test1.txt #<==输出每行的全部内容
hello world!
other men live to eat,while I eat to live.
It is never too late to mend.
[root@www jiaofan]# awk '{print NR}' test1.txt test2.txt #<==打印当前行号
1
2
3
4
5
6
[root@www jiaofan]# awk '{print FNR}' test1.txt test2.txt #<==打印当前文件行号
1
2
3
1
2
3
[root@www jiaofan]# awk '{print FILENAME}' test1.txt test2.txt
test1.txt
test1.txt
test1.txt
test2.txt
test2.txt
test2.txt
[root@www jiaofan]#
2、自定义变量(-v)
[root@www jiaofan]# awk -v x="jiaofan" -v y=11 '{print x,y}' test1.txt
jiaofan 11
jiaofan 11
jiaofan 11
[root@www jiaofan]# x="hello"
[root@www jiaofan]# awk -v i=$x '{print i}' test1.txt #<==输出变量
hello
hello
hello
[root@www jiaofan]# awk '{print "'$x'"}' test1.txt #<==输出变量
hello
hello
hello
定义分隔符:FS 或 F
[root@www jiaofan]# cat test2.txt
biscuit:crisp:chichen
salt-jam:oil,suger
banana:lemon,pear--apple:grape
[root@www jiaofan]# awk -v FS=":" '{print $1}' test2.txt #<==以:为分隔符
biscuit
salt-jam
banana
[root@www jiaofan]# awk -v FS="[:,-]" '{print $1}' test2.txt #<==以:和-为分隔符
biscuit
salt
banana
[root@www jiaofan]# awk -F":" '{print $1}' test2.txt #<==以:为分隔符
biscuit
salt-jam
banana
[root@www jiaofan]# awk -F"[:,-]" '{print $1}' test2.txt #<==以:和-为分隔符
biscuit
salt
banana
[root@www jiaofan]#
输入行分隔符,默认是\n,可以修改RS自定义分隔符
[root@www jiaofan]# cat test1.txt
hello world!
other men live to eat,while I eat to live.
It is never too late to mend.
[root@www jiaofan]# awk -v RS="," '{print $1}' test1.txt
hello
while
上面以逗号问行分隔符,所以输入内容为两行分别是
hello world!\nother men live to eat
while I eat to live.\nIt is never too late to mend.
输出字段分隔符OFS
[root@www jiaofan]# awk '{print $3,$1,$3}' test1.txt #<==默认是空格为分隔符
hello
live other live
never It never
[root@www jiaofan]# awk -v OFS=":" '{print $3,$1,$3}' test1.txt #<==设置冒号为分隔符
:hello:
live:other:live
never:It:never
[root@www jiaofan]# awk -v OFS="-" '{print $3,$1,$3}' test1.txt
-hello-
live-other-live
never-It-never
[root@www jiaofan]# awk -v OFS="\t" '{print $3,$1,$3}' test1.txt #<==设置制表符为分隔符
hello
live other live
never It never
[root@www jiaofan]# awk -v OFS="." '{print NR,$0}' test1.txt
1.hello world!
2.other men live to eat,while I eat to live.
3.It is never too late to mend.
输出行分隔符ORS
[root@www jiaofan]# cat test1.txt
hello world!
other men live to eat,while I eat to live.
It is never too late to mend.
[root@www jiaofan]# awk -v ORS=":" '{print}' test1.txt
hello world!:other men live to eat,while I eat to live.:It is never too late to mend.:
3、print 指令
[root@www jiaofan]# awk '{print "data:",$1}' test1.txt
data: hello
data: other
data: It
[root@www jiaofan]# awk '{print 12345}' test1.txt
12345
12345
12345
[root@www jiaofan]# awk '{print $1,12345,$3}' test1.txt
hello 12345
other 12345 live
It 12345 never
[root@www jiaofan]# awk '{print "第一列",$1,"\t第二列:",$2}' test1.txt
第一列 hello 第二列: world!
第一列 other 第二列: men
第一列 It 第二列: is
4、条件匹配
比较符号 | 描述 |
---|---|
// | 全行数据正则匹配 |
!// | 对全行数据正则匹配后取反 |
~// | 对特定数据正则匹配 |
!~// | 对特定数据正则匹配后取反 |
== | 等于 |
!= | 不等于 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
&& | 逻辑与,如A&&B,要求满足A并且满足B |
|| | 逻辑或,如A||B,要求满足A或者满足B |
[root@www jiaofan]# cat test1.txt #<==准备素材
hello the world!
other men live to eat,while I eat to live.
It is never too late to mend.
[root@www jiaofan]# awk '/the/' test1.txt #<==每行正则匹配the
hello the world!
other men live to eat,while I eat to live.
[root@www jiaofan]# awk '$2~/the/' test1.txt #<==每行第二列正则匹配the
hello the world!
[root@www jiaofan]# awk '$4==to' test1.txt #<==每行第四列精确匹配the
hello the world!
[root@www jiaofan]# awk -F: '$3>=100' /etc/passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
nisuser1:x:1001:1001::/home/nisuser1:/bin/bash
nisuser2:x:1002:1002::/home/nisuser2:/bin/bash
nisuser3:x:1003:1003::/home/nisuser3:/bin/bash
[root@www jiaofan]# awk 'NR==4' /etc/passwd
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@www jiaofan]# awk -F: '$3>1 && $3<5' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@www jiaofan]# awk -F: '$3==1 || $3==5' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
[root@www jiaofan]#
awk 的匹配条件可以使BEGIN 或 END(大写字母),BEGIN 会导致动作指令仅在读取任何数据记录之前执行一次,END 会导致动作指令仅在读取完所有数据记录后执行一次。利用 BEGIN 我们可以进行数据的初始化操作,而 END 则可以帮助我们进行数据的汇总操作。
[root@www jiaofan]# awk -F: 'BEGIN{print "用户名 UID 解释器"} {print $1,$3,$7} END{print "总计有"NR"个账户。"}' /etc/passwd | column -t
用户名 UID 解释器
root 0 /bin/bash
bin 1 /sbin/nologin
daemon 2 /sbin/nologin
... ...
总计有25个账户。
[root@www jiaofan]# awk 'BEGIN{print 10-4}'
6
[root@www jiaofan]# awk 'BEGIN{x=8;y=2;print x-y}' #<==对变量进行减法
6
在awk中变量不需要定义就可以直接使用,作为字符处理时未定义的变量默认值为空,作为数字处理时未定义的变量默认值为0
[root@www jiaofan]# awk 'BEGIN{print x+8}'
8
[root@www jiaofan]# awk 'BEGIN{print "["x"]","["y"]"}'
[] []
[root@www jiaofan]# who | awk '$1=="root"{x++} END{print x}'
2
[root@www jiaofan]# ls -l /etc/*.conf | awk '{sum+=$5} END{print sum}'
44107
[root@www jiaofan]# ls -l /etc/*.conf | awk '/^-/{sum+=$5} END{print "文件总量:"sum"."}'
文件总量:44107.
[root@www jiaofan]#
二、条件判断
awk单支语句
if(判断条件){
动作指令序列;
}
awk双支语句
if(判断条件){
动作序列1;
}
else{
动作序列2;
}
awk多支语句
if(判断条件1){
动作序列1;
}
else if(判断条件2){
动作序列1;
}
else{
动作序列2;
}
三、awk 数组
一维数组:
数据名[索引]=值
多维数组:
数据名[索引1][索引2]=值
或者
数据名[索引1,索引2]=值
for循环读取索引
for(变量 in 数据名){
动作指令序列
}
判断索引是否为数组成员
if (索引 in 数据)
四、awk 循环
for循环
for(表达式1;表达式2;表达式3){
动作指令序列
}
while 循环
while(条件判断){
动作指令序列;
}
五、awk 函数
1、内置I/O函数
函数 | 说明 |
---|---|
getline | getline会读取下一条数据,而不会影响后续awk指令的执行 |
next | next不仅读取下一行数据,会导致后续的指令不再执行,而是重新读取数据后重新回到awk指令的开始位置,重新匹配,重新执行动作指令 |
system(“命令”) | awk会启动一个新的shell进程执行命令 |
[root@www jiaofan]# cat test.txt
1:hello the world.
2:go spurs air.
3:123 456 789.
4:hello the beijing.
[root@www jiaofan]# awk '/air/{getline;print "next line:",NR,$0} {print "noraml line NR="NR}' test.txt
noraml line NR=1
next line: 3 3:123 456 789.
noraml line NR=3
noraml line NR=4
[root@www jiaofan]# awk '/air/{next;print "next line:",$0} {print "noraml line NR="NR}' test.txt
noraml line NR=1
noraml line NR=3
noraml line NR=4
[root@www jiaofan]# awk 'BEGIN{system("uptime")}'
16:44:45 up 6:56, 3 users, load average: 0.00, 0.01, 0.05
[root@www jiaofan]# awk 'BEGIN{system("echo jiaofan")}'
jiaofan
2、内置数值函数
函数 | 说明 |
---|---|
cos(expr) | 函数返回expr的cosine值 |
sin(expr) | 函数返回expr的sine值 |
sqrt(expr) | 函数返回expr的平方 |
int(expr) | 函数为取整函数,仅截取整数部分的数值 |
rand() | 函数可以返回0到1之间的随机数N(0<=N<1) |
srand() | 函数可以使用expr定义新的随机数种子,没有expr时则使用当前系统的时间为随机数种子 |
[root@www jiaofan]# awk 'BEGIN{print cos(50)}'
0.964966
[root@www jiaofan]# awk 'BEGIN{print sin(50)}'
-0.262375
[root@www jiaofan]# awk 'BEGIN{print sqrt(2)}'
1.41421
[root@www jiaofan]# awk 'BEGIN{print sqrt(4)}'
2
[root@www jiaofan]# awk 'BEGIN{print int(4.6)}'
4
[root@www jiaofan]# awk 'BEGIN{print rand()}'
0.237788
[root@www jiaofan]# awk 'BEGIN{for(i=1;i<=5;i++)print rand()}'
0.237788
0.291066
0.845814
0.152208
0.585537
[root@www jiaofan]# awk 'BEGIN{print 100*rand()}'
23.7788
[root@www jiaofan]# awk 'BEGIN{print rand()}' #<==没有新种子随机数固定
0.237788
[root@www jiaofan]# awk 'BEGIN{srand();print rand()}' #<==使用时间做随机数
0.217179
[root@www jiaofan]# awk 'BEGIN{srand(897);print rand()}' #<==使用897做随机数
0.504158
[root@www jiaofan]# awk 'BEGIN{srand(897);print rand()}'
0.504158
3、内置字符串函数
length([s]) 函数可以统计字符串s的长度,如果不指定字符串 s 则统计$0的长度。
[root@www jiaofan]# awk 'BEGIN{test="hello the world";print length(test)}'
15
index(字符串1,字符串2) 函数返回字符串2在字符串1中的位置坐标。
[root@www jiaofan]# awk 'BEGIN{test="hello the world";print index(test,"h")}' #<==h在test变量的第一个位置
1
[root@www jiaofan]# awk 'BEGIN{test="hello the world";print index(test,"t")}' #<==t在test变量的第一个位置
7
match(s,r) 函数根据正则表达式 r 返回其在字符串s中的位置坐标。
[root@www jiaofan]# awk 'BEGIN{print match("How much? 981$","[0-9]")}' #<==数字在第11个位置出现
11
[root@www jiaofan]# awk 'BEGIN{print match("How 4much? 981$","[0-9]")}' #<==数字在第5个位置出现
5
[root@www jiaofan]# awk 'BEGIN{print match("How much? 981$","[a-z]")}'
2
[root@www jiaofan]# awk 'BEGIN{print match("How much? 981$","[A-Z]")}'
1
tolower(str) 函数可以将字符串转换为小写
[root@www jiaofan]# awk 'BEGIN{apple[0]="red aPPLe";print tolower(apple[0])}'
red apple
toupper(str) 函数可以将字符串转换为大写。
[root@www jiaofan]# awk 'BEGIN{apple[0]="red aPPLe";print toupper(apple[0])}'
RED APPLE
split(字符串,数组,分隔符) 函数可以将字符串按特定的分隔符切片后存储在数组中,如果没有指定分隔符,则使用FS定义的分隔符进行字符串分隔。
[root@www jiaofan]# awk 'BEGIN{split("hello the world",test);print test[1],test[2]}'
hello the
这条命令以空格或Tab键为分隔符,将hello the world 切割为独立的三个部分,分别存入 test[1]、test[2]、test[3] 数组中,最后通过 print 指令可以按照任意顺序打印显示这些数组元素的值。
[root@www jiaofan]# awk 'BEGIN{split("hello:the:world",test);print test[1] test[2]}' #<==test[2]为空值
hello:the:world
[root@www jiaofan]# awk 'BEGIN{split("hello:the:world",test,":");print test[1] test[2]}' #<==自定义分隔符为冒号
hellothe
[root@www jiaofan]# awk 'BEGIN{split("hello:the:world",test,":");print test[1],test[2]}'
hello the
[root@www jiaofan]# awk 'BEGIN{split("hi8the3world4!",test,"[0-9]");print test[1],test[4]}' #<==使用正则定义分隔符
hi !
[root@www jiaofan]#
gsub(r,s,[,t]) 函数可以将字符串 t 中所有的正则表达式 r 匹配的字符串全部替换为 s ,如果没有指定字符串 t ,默认对$0进行替换操作。
[root@www jiaofan]# awk 'BEGIN{hi="hello world";gsub("o","O",hi);print hi}' #<==小写o换成大写O
hellO wOrld
[root@www jiaofan]# head -1 /etc/passwd | awk '{gsub("[0-9]","**");print $0}' #<==全部的数字替换成**
root:x:**:**:root:/root:/bin/bash
sub(r,s,[,t]) 函数与gsub类似,但仅替换第一个匹配的字符串,而不是替换全部。
[root@www jiaofan]# head -1 /etc/passwd | awk '{sub("[0-9]","**");print $0}'
root:x:**:0:root:/root:/bin/bash
[root@www jiaofan]# head -1 /etc/passwd | awk '{sub("root","**");print $0}'
**:x:0:0:root:/root:/bin/bash
substr(s,i[,n]) 函数可以对字符串s 进行截取,从第i位开始,截取n个字符串,如果n没有指定则一直截取到字符串s的末尾位置。
[root@www jiaofan]# awk 'BEGIN{hi="hello world";print substr(hi,2,3)}' #<==从第2位开始截取3个字符
ell
[root@www jiaofan]# awk 'BEGIN{hi="hello world";print substr(hi,2)}' #<==从第2位开始截取到末尾
ello world
4、内置时间函数
systime() 返回当前时间距离1970-01-01 00:00:00 有多少秒。
[root@www jiaofan]# awk 'BEGIN{print systime()}'
1646017041
[root@www jiaofan]#