
AWK常见用法(一)
一、初识AWK
AWK有其他的衍生版本,比如nawk和gawk,在Linux发行版里,默认使用的是gawk:
# ls -l `which awk`
lrwxrwxrwx. 1 root root 4 5月 9 20:25 /usr/bin/awk -> gawk
二、AWK的工作流程
AWK是按行处理文本,将行按照某一分隔符进行分割,其中分割之后的第一部分为$1,第二部分为$2,依次类推,其中$0表示整行,超过10的要将数字用括号括起来,比如$(10)AWK默认的分隔符是空格和tab,其中操作命令必须写在{}里面,语法:
awk '/模式/{print $1}' file //模式支持正则表达式,只对含有该模式的行进行操作
- 可以使用
-F选项指定分隔符:
awk -F: '/模式/{print $1}' file
三、常见操作符的使用(例子中passwd文件使用/etc/passwd文件的前6行)
常见的操作符有:~、!~、==、!=、>、<、++、--等
~和!~表示包含和不包含:
# awk -F: '$1~/ro/{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
==和!=表示严格的等于和不等于:
# awk -F: '$3==1{print $0}' passwd
bin:x:1:1:bin:/bin:/sbin/nologin
# awk -F: '{$3++;print $3}' passwd
1
2
3
4
5
6
- 其他的一些操作符同理,两个以上的条件需要使用连接符
&&或||
四、AWK中 BEGIN 和 NED 的用法
BEGIN中的命令是在AWK读取文本的第一行之前进行操作:
# awk -F: 'BEGIN{print "用户名"}{print $1}' passwd
用户名
root
bin
daemon
adm
lp
sync
END中的命令是在读取完最后一行之后进行的操作:
# awk -F: '{print $1}END{print "结束"}' passwd
root
bin
daemon
adm
lp
sync
结束
- BEGIN和END可以同时出现,也可以单独出现,BEGIN中可以定义变量:
# awk -F: 'BEGIN{a=1}{print a}' passwd
1
1
1
1
1
1
如何没有预先定义变量的话,在后面也是可以引用的,只不过这个变量的值为空。引用变量的时候不加$
END中也可以进行最终的计算:
# awk -F: 'BEGIN{sum=0}{sum+=$3}END{print "所有UID的和为:"sum}' passwd
所有UID的和为:15
或者不预先定义变量:
# awk -F: '{sum+=$3}END{print "所有UID的和为:"sum}' passwd
所有UID的和为:15
五、AWK中常见内置变量的用法
FS代表分隔符:
# awk 'BEGIN{FS=":"}{print $1}' passwd
root
bin
daemon
adm
lp
sync
OFS为打印输出的分隔符,默认的是空格:
# awk 'BEGIN{FS=":";OFS="---"}{print $1,$2}' passwd
root---x
bin---x
daemon---x
adm---x
lp---x
sync---x
NF的值表示将每一行按照FS指定的分隔符分为多少段:
# awk 'BEGIN{FS=":"}{print NF}' passwd
7
7
7
7
7
7
如果要打印每一行的最后一段,可以使用以下用法:
# awk 'BEGIN{FS=":"}{print $NF}' passwd
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
- 前面提到过,AWK是将文件按行进行处理,那么AWK是如何分别每一行的呢?使用的就是
RS的值,默认为\n:
# cat test.txt
1,张三:经理 2,李四:职员 3,王五:老板
# awk -F[:,] 'BEGIN{RS=" "}{print $2,$3}' test.txt
张三 经理
李四 职员
王五 老板
ORS变量的值决定输出行的分隔符,默认的为\n:
# awk 'BEGIN{ORS="---"}{print $0}' passwd
root:x:0:0:root:/root:/bin/bash---bin:x:1:1:bin:/bin:/sbin/nologin---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---sync:x:5:0:sync:/sbin:/bin/sync---
FILENAME变量的值为当前操作文件的文件名:
# awk -F: '{print FILENAME}' passwd
passwd
passwd
passwd
passwd
passwd
passwd
NR变量的值表示当前正在操作的行号:
# awk -F: '{print NR}' passwd
1
2
3
4
5
6
如果这里将行分隔符RS赋值为-,验证NR的值:
# awk 'BEGIN{RS="-"}{print NR}' passwd
1
FNR也表示当前操作的行号,不同的是,当对一个文件进行操作的时候FNR和NR的值是一样的。当对两个文件进行操作时,FNR和NR的值是不一样的:
# awk -F: '{print NR,$1,FNR}' passwd shadow
1 root 1
2 bin 2
3 daemon 3
4 adm 4
5 lp 5
6 sync 6
7 root 1
8 bin 2
9 daemon 3
10 adm 4
11 lp 5
12 sync 6
六、判断和循坏语句
if语句:
语法,如果语句没有使用{},则要使用;分隔
if(判断1){语句1}else if(判断2){语句2}else{语句3}
if(判断1)语句1;else if(判断2)语句2;else语句3
# awk -F: '{if($3==0){print $1"是root"}else if($3>=1000){print $1"是普通用户"}else{print $1"是系统用户"}}' passwd
root是root
bin是系统用户
daemon是系统用户
adm是系统用户
lp是系统用户
sync是系统用户
for循坏语句:
awk -F: '{for(i=1;i<=NF-5;i++){print $i}}' passwd
root
x
bin
x
daemon
x
while循坏语句:
# awk -F: '{print "------------";i=1;while(i<=NF){print $i;i++}}' passwd
------------
root
x
0
0
root
/root
/bin/bash
------------
bin
x
1
1
bin
/bin
/sbin/nologin
------------
daemon
x
2
2
daemon
/sbin
/sbin/nologin
- 循坏控制语句
break:
break只能用在循环语句中,作用是跳出当前循环,继续下一循环
# echo -e "1 2 3 4 1\n5 6 7" | awk '{for(i=1;i<=NF;i++){if($i>=2){break}print $i}}'
1
- 循环控制语句
continue:如果遇到continue,continue后面的语句不再执行,继续下一个循环
# echo -e "1 2 3 4 1\n5 6 7" | awk '{for(i=1;i<=NF;i++){if($i>=2){continue}print $i}}'
1
1
- 循环控制语句
next:遇到next,跳出循环,继续下移循环,在循环语句中next和break语句效果一样。区别在于,break和continue语句只能用于循环语句,next语句还可以用于其他语句,以下例子用于判断语句
# echo -e "1 2 3 4 1\n5 6 7 1" | awk '{if($2<=2){next}print $0}'
5 6 7 1
# awk -F: 'NR==FNR{print NR,FILENAME,FNR;next}{print NR,FILENAME,FNR}' passwd shadow
1 passwd 1
2 passwd 2
3 passwd 3
4 shadow 1
5 shadow 2
6 shadow 3
七、AWK中数组的使用
- 手动定义数组
# echo '' | awk '{aa[1]=1;aa[2]=2;aa["b"]="b";print aa[1]}'
1
- 读取文件
# awk -F: '{for(i=1;i<=NF;i++){a[i]=$i;print a[1];break}}' passwd
root
bin
daemon
# cat c1
01 北京
02 上海
03 广州
04 深圳
# cat c2
01 beijing
02 shanghai
03 guangzhou
04 shenzhen
# awk 'NR==FNR{a[$1]=$0}NR!=FNR{print a[$1],$2}' c1 c2
01 北京 beijing
02 上海 shanghai
03 广州 guangzhou
04 深圳 shenzhen
八、AWK中常见函数的使用
sub和gsub函数:用来替换
# cat test.txt
tom bob mary tom
bob tom mary tom
# awk '{sub("tom","TOM");print}' test.txt
TOM bob mary tom
bob TOM mary tom
但是只替换了每行的第一个,要想替换所有的,使用gsub函数:
# awk '{gsub("tom","TOM");print}' test.txt
TOM bob mary TOM
bob TOM mary TOM
只替换最后一个:
# awk '{gsub("tom","TOM",$NF);print}' test.txt
tom bob mary TOM
bob tom mary TOM
length函数用来计算字符串长度
# awk -F: '{print $1,length($1)}' passwd
root 4
bin 3
daemon 6
substr函数用来截取一段数据
# awk -F: '{print substr($1,2)}' passwd
oot
in
aemon
# awk -F: '{print substr($1,2,2)}' passwd
oo
in
ae
match函数的使用,从字符串中匹配满足某种格式的位置
# awk -F: '{xx=match($1,"oo");print xx}' passwd
2
0
0
match中有两个变量,RSTART可以获取到match得到的值,RLENGTH表示的是match中满足格式的字符创的长度,一般会结合substr截取我们所需要的数据:
# awk -F: '{xx=match($1,"oo");print xx,RSTART,RLENGTH}' passwd
2 2 2
0 0 -1
0 0 -1
split函数的使用:split("原始字符串",数组名,<分隔符>)
# echo '' | awk '{split("2018-05-20",xx,"-");print xx[1],xx[2],xx[3]}'
2018 05 20
# awk '{split($0,xx,":");print xx[1]}' passwd
root
bin
daemon
getline函数可以让我们使用操作系统命令,也可以读取另一个文件内容
# awk '{getline;print $0}' c1
02 上海
04 深圳
可以看到getline将本文件的下一行赋值给当前的$0
# awk '{getline xx;print $0,xx}' c1
01 北京 02 上海
03 广州 04 深圳
在这里将下一行的值赋值给了getline后的变量xx,并没有影响当前的$0
getline < file:该用法读取file文件的一行赋值给当前的$0
getline xx < file:该用法读取file文件的一行赋值给变量xx
# awk '{getline xx< "c2";print xx,$2}' c1
01 beijing 北京
02 shanghai 上海
03 guangzhou 广州
04 shenzhen 深圳
# echo '' | awk '{"date"|getline xx;print xx}'
2018年 05月 20日 星期日 19:57:04 CST
# echo '' | awk '{while("ls /boot"|getline xx) print xx}'
config-3.10.0-327.el7.x86_64
grub2
initramfs-0-rescue-ba7506401e184ceea617517542f6b7c7.img
initramfs-3.10.0-327.el7.x86_64.img
initrd-plymouth.img
symvers-3.10.0-327.el7.x86_64.gz
System.map-3.10.0-327.el7.x86_64
vmlinuz-0-rescue-ba7506401e184ceea617517542f6b7c7
vmlinuz-3.10.0-327.el7.x86_64
# echo '' | awk '{print "请输入:";getline name<"/dev/tty";print "你好:" name}'
请输入:
tom
你好:tom
九、AWK的格式化输出
printf不带换行符
# awk -F: '{printf "%-8s|%-5d\n",$1,$3}' passwd
root |0
bin |1
daemon |2
其中%-8s中的-8表示显示宽度为8个字符,-表示左对齐,+号表示右对齐
%d显示的整数
%f显示的是浮点数,%10.5f表示总共显示十位。小数点后显示5位
%e用科学计数法显示
# echo '' | awk '{printf "%d\n",3*3.5}'
10
# echo '' | awk '{printf "%f\n",3*3.5}'
10.500000
# echo '' | awk '{printf "%-.10f\n",10/3}'
3.3333333333
# echo '' | awk '{printf "%e\n",3*3.5}'
1.050000e+01
Leave AWK常见用法(一) to:
Read more #linux posts
Best Posts From pmliang
We have not curated any of pmliang's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.