awk使用范例
-
原文件内容: [root@CentOS8 data]# cat emp.txt Beth:4.00:0 Dan:3.75:0 kathy:4.00:10 Mark:5.00:20 Mary:5.50:22 Susie:4.25:18
-
以 :为分隔符搜索 emp.txt 文件中每行的 1,3字段,且打印至终端时在其中间以 tab键为字段分隔符来显示 [root@CentOS8 data]# awk -F":" '{print $1"\t"$3}' emp.txt Beth 0 Dan 0 kathy 10 Mark 20 Mary 22 Susie 18
-
与-F作用相同的写法 -v FS= [root@CentOS8 data]# awk -v FS=":" '{print $1"\t"$3}' emp.txt Beth 0 Dan 0 kathy 10 Mark 20 Mary 22 Susie 18
-
指定 tab键 为字段分隔符显示 emp.txt 文件的1,3字段 OFS [root@CentOS8 data]# awk -v OFS="\t" -F":" '{print $1,$3}' emp.txt Beth 0 Dan 0 kathy 10 Mark 20 Mary 22 Susie 18
-
同样也可以这样写:应注意有两个 -v [root@CentOS8 data]# awk -v FS=':' -v OFS='\t' '{print $1,$3}' emp.txt Beth 0 Dan 0 kathy 10 Mark 20 Mary 22 Susie 18
-
另外,还可以输入记录分隔符,指定输入时的换行符 例如:以 ;为记录分隔符,只要遇到 ;就将 ;换成\n换行 应注意原文件每行结尾都有一个隐藏的\n换行符,输出结果仍将\n换行符视为某行的一部分 [root@CentOS8 data]# cat file.txt student;liming tech;wang;ma [root@CentOS8 data]# awk -v RS=';' '{print}' file.txt student liming tech wang ma
-
那么如何证明这一点呢? 输出行号一共为4行 [root@CentOS8 data]# awk -v RS=';' '{print NR}' file.txt 1 2 3 4 而之前的输出字符似乎是五行 : [root@CentOS8 data]# awk -v RS=';' '{print}' file.txt student liming tech wang ma 结论证明:NR为显示行号,$0是显示每一行;意思是输出每一行并为其添加行号 [root@CentOS8 data]# awk -v RS=';' '{print $0,NR}'le.txt student 1 liming tech 2 wang 3 ma 4 所以第一行的liming \n tech三者被视为同一新行,此外,ma后面依旧有一个隐藏的\n换行符
-
使用ORS输出记录分隔符,输出时用指定符号代替换行符 只要遇到 ;就将其替换成@@@输出 若RS不指定,默认将行尾隐藏的\n换行符替换 [root@CentOS8 data]# awk -v RS=';' -v ORS='@@@' '{print $0}' file.txt student@@@liming tech@@@wang@@@ma @@@
-
还可以使用NF来显示每一行的字段个数 [root@CentOS8 data]# awk -v RS=';' '{print NF}' file.txt 1 2 1 1
-
当然,如果不添加额外的选项,仅显示原文件的话,此时只有两行,如果该行中没有空格分隔字段,那么该行会被视为一个整体 即:一个字段 [root@CentOS8 data]# awk '{print NF}' file.txt 1 1
-
取出磁盘最大使用率 [root@CentOS8 data]# df -h|grep 'dev/sd'|awk -F% '{print $1}'|awk '{print $5}'|sort -n|tail -1 13
-
另一种写法 [root@CentOS8 data]# df -h|awk -F" +|%" '$0 ~ /^\/dev\/sd/{print $5}'|sort -n|tail -1 13
-F 指明输入时选定的字段分隔符
-v Var=value
变量赋值
FS 输入字段分隔符,默认为空格
OFS 输出字段分隔符,默认为空格
RS 输入记录分隔符,指定输入时的换行符
ORS 输出记录分隔符,输出时用指定符号代替换行符
NF 显示字段数量
NR 记录每行行号
-
除了处理一个文件,是不是可以处理多个文件呢? 同时分别显示两个文件的行号 [root@CentOS8 data]# cat file.txt student;liming tech;wang;ma [root@CentOS8 data]# cat emp.txt Beth:90:one Dan:110:two [root@CentOS8 data]# awk '{print FNR}' file.txt emp.txt 1 2 1 2 [root@CentOS8 data]# awk '{print $0,FNR}' file.txt emp.txt student;liming 1 tech;wang;ma 2 Beth:90:one 1 Dan:110:two 2
-
另外还有其他有意思的选项 有关NR、NF变量的使用 在以前我们曾尝试用各种基础命令来取出IP地址、磁盘利用率、软件版本类型等等如此之类的需求;而awk可以非常便捷的做到 : 取出磁盘利用率最大的分区 [root@CentOS8 data]# df -h|awk -F" +|%" '$0~"/dev/sda"{print $5}'|sort -n|tail -1 13
-
取出用户的家目录 [root@CentOS8 data]# awk -F: '{print $(NF-1)}' /etc/passwd /root /bin …………. /home/td /home/mage
-
取出主机ip [root@CentOS8 data]# ifconfig ens33|awk NR==2'{print $NR}' 192.168.124.3
-
有关FILENAME的使用 文件内容全部替换成文件名,即输出文件个数=文件行数 [root@CentOS8 data]# awk '{print FILENAME}' file.txt file.txt file.txt [root@CentOS8 data]# awk '{print FILENAME}' emp.txt emp.txt emp.txt [root@CentOS8 data]# awk '{print FNR,FILENAME}' emp.txt file.txt 1 emp.txt 2 emp.txt 1 file.txt 2 file.txt
-
?awk还可以加减乘除? [root@CentOS8 data]# awk 'BEGIN{print 3*5}' 15 [root@CentOS8 data]# awk 'BEGIN{print (2*5-6)/2^2}' 1
-
显示命令行参数的个数 [root@CentOS8 data]# awk 'BEGIN{print ARGC}' 1 [root@CentOS8 data]# awk 'BEGIN{print ARGC}' emp.txt 2 [root@CentOS8 data]# awk 'BEGIN{print ARGC}' emp.txt file.txt 3 [root@CentOS8 data]# awk 'BEGIN{print ARGC}' emp.txt file.txt pig.txt 4
-
ARGV:数组 [root@CentOS8 data]# awk 'BEGIN{print ARGV[0]}' emp.txt file.txt pig.txt awk [root@CentOS8 data]# awk 'BEGIN{print ARGV[1]}' emp.txt file.txt pig.txt emp.txt [root@CentOS8 data]# awk 'BEGIN{print ARGV[2]}' emp.txt file.txt pig.txt file.txt [root@CentOS8 data]# awk 'BEGIN{print ARGV[3]}' emp.txt file.txt pig.txt pig.txt
-
FNR 分别记录多个文件行号 FILENAME 当前文件名 ARGC 终端输入时命令行参数的个数 BEGIN 加减乘除等运算 ARGV 数组,命令行的各个参数
-
除了可以使用awk的内置变量,还可以自定义变量 [root@CentOS8 data]# awk -F: -v user="username : " '{print user$1}' /etc/passwd username : root username : bin username : daemon username : adm ……………………………
-
自定义多个变量 [root@CentOS8 data]# awk -F: -v user="username : " -v usid="useruid : " -v ugid= :" usergid " '{print user$1"\t"usid$3"\t"ugid$4}' /etc/passwd username : root useruid : 0 usergid :0 username : bin useruid : 1 usergid :1 username : daemon useruid : 2 usergid :2 username : adm useruid : 3 usergid :4 ……………………………………
-
也可以将变量定义在program中 [root@CentOS8 data]# awk -F: '{user="username : ";usid="useruid : ";ugid=" usergid :";print user$1"\t"usid$3"\t"ugid$4}' /etc/passwd username : root useruid : 0 usergid :0 username : bin useruid : 1 usergid :1 username : daemon useruid : 2 usergid :2 username : adm useruid : 3 usergid :4 ………………………………………………
-
倘若你已经在shell中定义过要使用的变量,同样在awk中你也可以调用它 [root@CentOS8 data]# user="username:" uuid="useruid:" ugid="usergid:";awk -F: -v i=$user -v u=$uuid -v g=$ugid '{print i$1"\t"u$3"\t"g$4}' /etc/passwd username:root useruid:0 usergid:0 username:bin useruid:1 usergid:1 username:daemon useruid:2 usergid:2 username:adm useruid:3 usergid:4 …………………………………………
-
将执行的命令放在一个文件中,使用awk调用该文件一样OK [root@CentOS8 data]# vim awk.txt [root@CentOS8 data]# cat awk.txt {user="username : ";usid="useruid : ";ugid=" usergid ";print user$1"\t"usid$3"\t"ugid$4} [root@CentOS8 data]# awk -F: -f awk.txt /etc/passwd username : root useruid : 0 usergid 0 username : bin useruid : 1 usergid 1 username : daemon useruid : 2 usergid 2 username : adm useruid : 3 usergid 4 ………………………………
printf命令
格式化输出:printf “FORMAT”,item1,item2,….
必须指定FORMAT
不主动换行,需手动给出\n换行符
FORMAT中需要分别为后面每个item指定格式符
格式符:与item相呼应
%c:显示字符的ASCII码(不常用)
%d,%i:显示十进制整数(常用)
%e,%E:显示科学计数法数值
%f:显示为浮点数(小数位)
%g,%G:以科学计数法或浮点形式显示数值(也许你需要将小数精确至0.001什么的)%s:显示字符串%u:无符号整数%%:显示%自身
修饰符:
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度 %3.1f
- 左对齐(默认为右对齐)%-15s
+ 显示数值的正负号 %+d
-
默认向右对其显示 [root@CentOS8 data]# cat emp.txt Beth:-90:233:-12:seur:out Dan:110:-7:66:root [root@CentOS8 data]# awk -F: '{printf "%4s %10d %5d\n",$1,$3,$4}' emp.txt Beth 233 -12 Dan -7 66
-
加-左对齐 [root@CentOS8 data]# awk -F: '{printf "%-4s %-10d %d\n",$1,$3,$4}' emp.txt Beth 233 -12 Dan -7 66
-
显示’数值‘的正负 [root@CentOS8 data]# awk -F: '{printf "%-5s %5+d %5+d\n",$1,$3,$4}' emp.txt Beth +233 -12 Dan -7 +66
-
之前操作的示例中有计算加减乘除的展示 那么,awk中的算术操作符以及其他的操作符有哪些:
x+y 加法
x-y 减法
x*y 乘法
x/y 除法
x^y 幂运算(指数)
x%y 取模(除余)
-x 转换成负数
+x 将字符串转换为数值
赋值操作符:
= 右边赋值给左边
+= 先加,再赋值
-= 先减,再赋值
*= 先乘,再赋值
/= 先除,再赋值
%= 先取模,再赋值
^= 先幂运算,再赋值
++ 递增操作
-- 递减操作
比较操作符:
== 判断相等
!= 判断不等
\> 判断大于
\>= 判断大于等于
< 判断小于
<= 判断小于等于
模式匹配符:
~ 左边是否和右边匹配包含
!~ 是否不匹配
逻辑操作符:
&& 逻辑与
|| 逻辑或
! 逻辑非
-
比较下列两个命令语句有何区别 [root@CentOS8 data]# awk 'BEGIN{i=0;print ++i,i}' [root@CentOS8 data]# awk 'BEGIN{i=0;print i++,i}'
-
第一个是先加,之后将加得的数和i打印 第二个是先打印i的值,再将i加得的数打印 [root@CentOS8 data]# awk 'BEGIN{i=0;print ++i,i}' 1 1 [root@CentOS8 data]# awk 'BEGIN{i=0;print i++,i}' 0 1
-
awk中的PATTERN模式
PATTERN:根据pattern条件,过滤匹配的行;然后再做处理
1:若pattern未指定:视为空模式,匹配所有行
2:/relational expression/:仅处理能够被模式匹配到的行,且需要用//扩入
3:relational expression:关系表达式,仅结果为真,才会进行处理
真:结果为非0值,非空字符串都为真
假:结果为空字符串或0值都为
4:line ranges:行范围
startine,endline:/pat1/,/pat2/不支持直接给出数字格式。
5:BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次。
-
匹配/etc/passwd 中所有行的第N个字段所在的那行包含root的 [root@CentOS8 data]# awk -F: '$0 ~ /root/{print $1}' /etc/passwd root operator
-
当然,如果匹配一个不存在的字符串是没有反应的 [root@CentOS8 data]# awk -F: '$0 ~ /kxxxla/{print $1}' /etc/passwd [root@CentOS8 data]# awk -F: '$0 ~ /root/{print $3}' /etc/passwd 0 11 [root@CentOS8 data]# awk -F: '$0 ~ /root/{print $5}' /etc/passwd root operator
-
查看/etc/passwd文件便可清楚了解 [root@CentOS8 data]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash …………………………………. operator:x:11:0:operator:/root:/sbin/nologin
-
匹配/etc/passwd 中所有行的第N个字段所在的那行为0的 [root@CentOS8 data]# awk -F: '$4==0' /etc/passwd root:x:0:0:root:/root:/bin/bash sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt operator:x:11:0:operator:/root:/sbin/nologin [root@CentOS8 data]# awk -F: '$3==0' /etc/passwd root:x:0:0:root:/root:/bin/bash
-
于此之外,使用!~可以匹配相反的效果 [root@CentOS8 data]# awk -F: '!$4==0' /etc/passwd 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
-
匹配/etc/passwd 中所有行的第N个字段所在的那行为非0的 [root@CentOS8 data]# awk -F: '!$4==0' /etc/passwd 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 …………………………………..过多不做演示
-
匹配/etc/passwd 中所有行的第N个字段所在的那行不包含root的 [root@CentOS8 data]# awkawk -F: '$0 !~ /root/{print $5}' tc/passwd bin daemon adm ………..过多不做演示
-
有关逻辑与或非的示例: 匹配/etc/passwd中所有行的第三字段数值在0-5之间的,打印符合条件的行的第一字段 [root@CentOS8 data]# awk -F: '$3>=0 && $3<=5 {print $1}' /etc/passwd|tr '\n' ' ' root bin daemon adm lp sync
-
匹配/etc/passwd中所有行的第三字段的数值在小于等于0或大于等于1000之间的,打印符合条件的行的第一字段 [root@CentOS8 data]# awk -F: '$3<=0 || $3>=1000 {print $1}' /etc/passwd root nobody td
-
匹配/etc/passwd中所有行的第三字段数值在小于1000的,取反变为大于等于1000的,打印符合条件的行的第一字段 [root@CentOS8 data]# awk -F: '!($3<1000) {print $1}' /etc/passwd nobody td
-
有关PATTERN模式的示例: 原文件:
[root@CentOS8 data]# cat /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Sep 25 20:03:53 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=e2e0f44d-0ae9-4159-a99f-6a1c72dcccbe / xfs defaults 0 0
UUID=deb9638d-76ba-4370-90f1-962cd4ab55b5 /boot ext4 defaults 1 2
UUID=40aac826-ee18-4927-8574-c8618c4ea1e7 /data xfs defaults 0 0
UUID=d12cdea2-cb68-4aa7-97cd-9002297faf05 swap swap defaults 0 0
-
仅匹显示以UUID开头的行 [root@CentOS8 data]# awk '/^UUID/{print $1}' /etc/fstab UUID=e2e0f44d-0ae9-4159-a99f-6a1c72dcccbe UUID=deb9638d-76ba-4370-90f1-962cd4ab55b5 UUID=40aac826-ee18-4927-8574-c8618c4ea1e7 UUID=d12cdea2-cb68-4aa7-97cd-9002297faf05
-
取反
[root@CentOS8 data]# awk '!/^UUID/{print $0}' /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Sep 25 20:03:53 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
-
Relational expression:关系表达式 [root@CentOS8 data]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd root /bin/bash td /bin/bash mage /bin/bash