awk本身是一种编程语言,主要用于unix/linux里对文本进行处理,也是一个工具。awk处理数据也是逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,在这些行上进行你所要的操作,如果没有处理动作,它也会显示到标准输出(屏幕)如果没有指定模式,那么对所有的行进行处理。我们现在所用的awk其实是gawk
[root@server ~]# which awk
/usr/bin/awk
[root@server ~]# ll /usr/bin/awk
lrwxrwxrwx. 1 root root 4 4月 24 06:05 /usr/bin/awk -> gawk
awk 【选项】‘commands’ filename
如果需要引用变量则用双引号,可以和正则一起使用
动作要用花括号{}包住,多个语句用分号;隔开
常用选项:
-F 定义字段分隔符,默认分隔符是空格或制表符
-v 定义变量并赋值
-f 指定文件里的命令来处理文件
commands命令部分:
BEGIN{}:读文件之前的动作,通常用于定义变量
{}:处理文件
END{}:读文件之后的动作
变量 | 含义 |
---|---|
NR | 行号 NR==1,NR<=5 |
NF | 行的字段个数(列数) |
FS | 分隔符,默认为空格 |
OFS | 定义输出字段分隔符,默认空格 |
RS | 输入记录分隔符,默认换行 |
ORS | 输出记录分隔符,默认换行 |
$0 | 当前处理行的所有记录 |
$1,$2… | 文件中每行以间隔符号分隔的不同字符 |
打印第一列内容,没有指定字段分隔符,默认是以空格分隔
[root@server ~]# awk '{print $1}' /etc/hosts
127.0.0.1
::1
以冒号分隔,打印第一列内容
[root@server ~]# awk -F: '{print $1}' passwd.txt
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
以冒号分隔,打印第一列和第二列内容
[root@server ~]# awk -F: '{print $1,$2}' passwd.txt
root x
bin x
daemon x
adm x
lp x
sync x
shutdown x
halt x
mail x
operator x
处理之前做什么动作→处理文件→处理完了做什么动作,不一定成对出现
打印第一列之前,声明分隔符为冒号
[root@server ~]# awk BEGIN'{FS=":"} {print $1}' passwd.txt
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
以冒号分隔,打印第一列和第二列
[root@server ~]# awk BEGIN'{FS=":"} {print $1,$2}' passwd.txt
root x
bin x
daemon x
adm x
lp x
sync x
shutdown x
halt x
mail x
operator x
以冒号分隔,字段输出符为–,打印第一列和第二列
[root@server ~]# awk BEGIN'{FS=":";OFS="--"} {print $1,$2}' passwd.txt
root--x
bin--x
daemon--x
adm--x
lp--x
sync--x
shutdown--x
halt--x
mail--x
operator--x
跟sed一样,awk也可以使用正则表达式,也是用在/ /中间
打印root所在的行
[root@server ~]# awk '/root/' passwd.txt
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
不打印root所在的行
[root@server ~]# awk '!/root/' passwd.txt
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
以冒号分隔,打印第三列等于0的行
[root@server ~]# awk -F: '$3==0' passwd.txt
root:x:0:0:root:/root:/bin/bash
这里如果是字符串的话等号右边需要用双引号将字符串引起来
以冒号分隔,打印第七列等于/bin/bash的行
[root@server ~]# awk -F: '$7=="/bin/bash"' passwd.txt
root:x:0:0:root:/root:/bin/bash
以冒号分隔,打印第三列小于5的行,{print $0}不写默认也是打印
[root@server ~]# awk -F: '$3<5{print $0}' passwd.txt
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
打印root所在行的第一列
[root@server ~]# awk -F: '/root/{print $1}' passwd.txt
root
operator
打印每一行和每一行的行号,中间用空格分隔,两个文件NR行号是累加的
[root@server ~]# awk '{print NR,$0}' passwd.txt /etc/hosts
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
11 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
12 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
打印两个文件的行号,FNR行号是不累加的,是分别打印的
[root@server ~]# awk '{print FNR,$0}' passwd.txt /etc/hosts
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
1 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
2 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
打印第一行到第五行的行号和内容
[root@server ~]# awk 'NR==1,NR==5{print NR,$0}' passwd.txt
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
打印第一行或者打印第五行的内容
[root@server ~]# awk 'NR==1 || NR==5{print $0}' passwd.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
打印第三行到第五行的内容
[root@server ~]# awk 'NR>=3 && NR<=5{print $0}' passwd.txt
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@server ~]# awk -F: '{print NF,$NF}' passwd.txt
7 /bin/bash
7 /sbin/nologin
7 /sbin/nologin
7 /sbin/nologin
7 /sbin/nologin
7 /bin/sync
7 /sbin/shutdown
7 /sbin/halt
7 /sbin/nologin
7 /sbin/nologin
以冒号分隔,打印倒数第二列
[root@server ~]# awk -F: '{print $(NF-1)}' passwd.txt
/root
/bin
/sbin
/var/adm
/var/spool/lpd
/sbin
/sbin
/sbin
/var/spool/mail
/root
以冒号和制表符为分隔,打印第三列
[root@server ~]# cat 123.txt
1 2 3 4:5:6 7 8 9
[root@server ~]# awk -F"[:\t]" '{print $3}' 123.txt
6
[root@server ~]# awk -F"[:\t]" '{print $5}' 123.txt
8
RS是记录分割,默认是按换行符为一行内容的,而FS是以字段分割,注意区别!
RS意思是遇见谁就把它当做一行的分隔符,然后输出内容
ORS意思是本来每一行的分隔符是换行符,现在不想以换行符当做一行的分割,想以空格当每一行的间隔,那么ORS=“ ”就可以了
以空格分隔每一行内容并打印
[root@server ~]# awk -F: 'BEGIN{RS=" "};{print $0}' 123.txt
1
2
3
4:5:6 7 8 9
以制表符为分隔每一行内容并打印
[root@server ~]# awk -F: 'BEGIN{RS="\t"};{print $0}' 123.txt
1 2 3 4:5:6
7
8
9
每一行以制表符为分隔符分隔行
[root@server ~]# awk -F: 'BEGIN{ORS="\t"};{print $0}' 123.txt
1 2 3 4:5:6 7 8 9 [root@server ~]#
打印第二列内容并以空格为分隔符
[root@server ~]# awk -F: 'BEGIN{ORS=" "};{print $2}' 123.txt
5 [root@server ~]#
因为{print $1,$2}的$1和$2之间的逗号会映射到OFS变量的空格,所以我们输出第一列和第二列之间会以空格显示,那么我们不想输出的时候以空格分,那么你想用什么分就把逗号换成什么就可以了,如果不指定的话就是紧挨着输出
[root@server ~]# awk 'BEGIN{FS=":"};{print "用户名是"$1"****shell是:"$NF}' passwd.txt
用户名是root****shell是:/bin/bash
用户名是bin****shell是:/sbin/nologin
用户名是daemon****shell是:/sbin/nologin
用户名是adm****shell是:/sbin/nologin
用户名是lp****shell是:/sbin/nologin
用户名是sync****shell是:/bin/sync
用户名是shutdown****shell是:/sbin/shutdown
用户名是halt****shell是:/sbin/halt
用户名是mail****shell是:/sbin/nologin
用户名是operator****shell是:/sbin/nologin
打印第一列和第三列,中间不分隔
[root@server ~]# awk -F: '{print $1 $3}' passwd.txt
root0
bin1
daemon2
adm3
lp4
sync5
shutdown6
halt7
mail8
operator11
每一行都打印root
[root@server ~]# awk '{print "root"}' passwd.txt
root
root
root
root
root
root
root
root
root
root
花括号里print后面要跟变量,如果不是变量其他任何字符都需要用双引号引起来,你想打印什么它就会输出什么
[root@server ~]# date
2020年 07月 29日 星期三 17:03:14 CST
[root@server ~]# date | awk '{print "year:"$1"\n""month:"$2}'
year:2020年
month:07月
打印第一列第二列和第三列并对齐
[root@server ~]# awk -F: '{printf "%-15s %-10s %-15s\n",$1,$2,$3}' passwd.txt
root x 0
bin x 1
daemon x 2
adm x 3
lp x 4
sync x 5
shutdown x 6
halt x 7
mail x 8
operator x 11
printf默认是不换行的,所以要加上\n
%s表示字符类型,%d表示数值类型,%f表示浮点型
%-15s表示字符输出宽度一共15个字符,不足用空格不足到15位。
-表示左对齐,默认不加是右对齐
这样做的方式是可以使格式对齐