awk命令编辑

awk工作原理

逐行读取文本,默认以空格或tab键分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。

sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个“字段”然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。在使用awk命令的过程中,可以使用逻辑作符“&&”表示“与”、“||”表示“或”、“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加 减 乘 除 取余和乘方。

命令格式:

awk 选项 '模式或条件 {操作}'   文件1  文件2 ...

awk  -f 脚本文件 文件1  文件2

awk常见的内建变量(可直接用)如下所示:

FS

列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与“-F”作用相同
NF当前处理的行的字段个数
NR当前处理的行的行号(序数)
$0当前处理的行的整行内容
$n当前处理行的第n个字段(第n列)
FILENAME被处理的文件名
RS行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是‘\n’

 按行输出文本

[root@cx ~]# awk '{print}' test 
one
two
three
four
five
six
seven
night
nine
ten
eleven
twelve
[root@cx ~]# awk 'NR==1,NR==3 {print}' test 输出第一行到第三行的内容
one
two
three
[root@cx ~]# awk '(NR>=1)&&(NR<=3) {print}' test   
one
two
three
[root@cx ~]# awk 'NR==1||NR==3 {print}' test 
one
three        输出第一行和第三行的行内容
[root@cx ~]# awk '(NR%2)==0{print NR,$0}' test 
2 two
4 four
6 six
8 night
10 ten
12 twelve      输出偶数行的行号和内容
[root@cx ~]# awk '(NR%2)==1{print NR,$0}' test 
1 one
3 three
5 five
7 seven
9 nine
11 eleven      输出奇数行的行号和内容
[root@cx ~]# awk '/^root/ {print $0}' passwd  以/root/开头的行内容
root:x:0:0:root:/root:/bin/bash
[root@cx ~]# awk '/bash$/ {print $0}' passwd  以/bash/结尾的行内容
root:x:0:0:root:/root:/bin/bash
cx:x:1000:1000:cx:/home/cx:/bin/bash
[root@cx ~]# awk '/\/bin\/bash$/ {print $0}' passwd 以/bin/bash/结尾的行内容
root:x:0:0:root:/root:/bin/bash
cx:x:1000:1000:cx:/home/cx:/bin/bash
[root@cx ~]# awk -F: '/^root/ {print $1}' passwd   输出以/root/开头的行的第1个字段
root
[root@cx ~]# awk -F: '/^root/ {print $3}' passwd   输出以/root/开头的行的第3个字段
0
[root@cx ~]# awk -F: '/^root/ {print $1,$3}' passwd 输出以/root/开头的行的第1和第3个字段
root 0
[root@cx ~]# awk -F: '/^root/ {print $1,$3,$NF}' passwd 输出以/root/开头的行的第1第3和最后一个字段
root 0 /bin/bash 
[root@cx ~]# awk -F: '/^root/ {print $1","$3","$NF}' passwd 用逗号分隔字段
root,0,/bin/bash
[root@cx ~]# grep -c "nologin$" passwd  过滤出以nologin结尾的行数
36
[root@cx ~]# awk '/nologin$/ {print $0}' passwd | wc -l 统计行数
36
[root@cx ~]# awk 'BEGIN {x=0}; /nologin$/ {x++}; END{print x}' passwd 
36 赋值一个变量0,每出现一个nologin结尾的行数自加1,最后打印输出x的值就是出现的行数
[root@cx ~]# awk 'BEGIN {x=0}; /nologin$/ {x++;print x,$0}; END{print x}' passwd 
1 bin:x:1:1:bin:/bin:/sbin/nologin


BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作;
awk再处理指定的文本,之后再执行END模式中指定的动作,
END{}语句块中,往往会放入打印结果等语句

按字段输出文本

[root@cx ~]# awk -F: '$3<5 {print $0}' passwd  以:为分隔取第三个字段小于5的行打印行内容
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
ftp:123456
root:123456
[root@cx ~]# awk -F: '!($3>5) {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
ftp:123456
root:123456
取反 打印除了第三个字段大于5的行内容,即打印第三个字段小于5的行
[root@cx ~]# awk 'BEGIN {FS=":"};{if($3<=5) 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
ftp:123456
root:123456


先处理完BEGIN的内容,再打印文本里面的内容
[root@cx ~]# awk -F: '{max=($3>=$4)?$3:$4;{print$1, max}}' passwd 
root 0
bin 1
daemon 2
adm 4
lp 7
sync 5
shutdown 6
halt 7
mail 12
operator 11
games 100
ftp 50
nobody 99
systemd-network 192
#($3>$4)?$3:$4;三元运算符,如果第3个字段的值大于等于第4个字段的值,则把第3个字段的值赋给max,否则第4个字段的值赋给max
[root@cx ~]# awk '{print}' test 
one
two
three
four
five
six
seven
night
nine
ten
eleven
twelve
[root@cx ~]# awk '$1~"o" {print}' test 
one
two
four
输出第1个字段中包含“o”的行的第1个字段
[root@cx ~]# awk -F: '$1~"root" {print $0}' passwd 
root:x:0:0:root:/root:/bin/bash
root:123456
[root@cx ~]# awk -F: '($1~"root")&&(NF==7) {print $0}' passwd 
root:x:0:0:root:/root:/bin/bash
[root@cx ~]# awk -F: '($1~"root")&&(NF==7) {print $1,$2}' passwd 
root x
#输出第1个字段中包含root且有7个字段的行的第1、2个字段

[root@cx ~]# awk -F: '!($1~"root")&&($NF=="/bin/bash") {print $0}' passwd 
cx:x:1000:1000:cx:/home/cx:/bin/bash
#输出第1个字段中不包含root且最后一个个字段是/bin/bash的行
[root@cx ~]# awk -F: '($1~"root")&&($NF!="/bin/bash") {print $0}' passwd 
root:123456
#输出第1个字段中包含root且最后一个字段不是/bin/bash的行
!表示取反

 通过管道、双引号调用 Shell 命令

以:分隔PATH变量的行数

[root@cx ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@cx ~]# echo $PATH | awk 'BEGIN {RS=":"} {print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin

设置行分隔符RS为冒号,打印输出

 内存使用百分比

[root@cx ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           1963         708         195           4        1059        1046
Swap:          4095           8        4087
[root@cx ~]# free -m | awk '/Mem/ {print $3}'
708
[root@cx ~]# free -m | awk '/Mem/ {print $3/$2}'
0.360672
[root@cx ~]# free -m | awk '/Mem/ {print $3/$2"%"}'
0.360672%
[root@cx ~]# free -m | awk '/Mem/ {print $3/$2 * 100}'
36.0672
[root@cx ~]# free -m | awk '/Mem/ {print $3/$2 * 100"%"}'
36.0672%
[root@cx ~]# free -m | awk '/Mem/ {print ($2-$3)/$2 * 100"%"}'
63.9328%
  #查看当前内存使用百分比

进程查看 

 cpu空闲率

[root@cx ~]# top -b -n1 | awk -F, '/%Cpu/ {print $4}' | awk '{print $1}'
93.8
[root@cx ~]# top -b -n1 | awk -F, '/%Cpu/ {print $4}' | awk '{print 100-$1}'
6.2
[root@cx ~]# top -b -n1 | awk -F, '/%Cpu/ {print $4}' | awk '{print 100-$1"%"}'
6.2%


#查看当前CPU空闲率,(-b -n 1 表示只需要1次的输出结果)

 挂载使用率

 date作用

[root@cx ~]# date
2023年 05月 15日 星期一 15:26:34 CST
[root@cx ~]# date +%Y%m%d
20230515
[root@cx ~]# date +%Y-%m-%d
2023-05-15
[root@cx ~]# date +%F
2023-05-15
[root@cx ~]# date +%D
05/15/23
[root@cx ~]# date +"%Y%m%d %H:%M:%S"
20230515 15:29:36
[root@cx ~]# date +"%Y%m01"
20230501
[root@cx ~]# date +"%Y%m%d"
20230515
[root@cx ~]# date -d "1 month" +"%Y%m%d"
20230615
[root@cx ~]# date -d "-1 month" +"%Y%m%d"
20230415
[root@cx ~]# date -d "-1 month" +"%Y%m01"
20230401
[root@cx ~]# date -d "1 month ago" +"%Y%m01"
20230401
[root@cx ~]# date -d "-1 month ago" +"%Y%m01"
20230601
[root@cx ~]# date -d "yesterday" +"%Y%m%d"
20230514



[root@cx ~]# date -d "$(date +%Y%m01) -1 day" +%Y%m%d
20230430  上个月最后一天
[root@cx ~]# date -d "$(date -d "1 month" +%Y%m01) -1 day" +%Y%m%d
20230531    这个月最后一天

显示系统上次重启时间

date -d      #显示字符串所指的日期与时间。字符串前后必须加上双引号

date +"%Y-%m-%d"      #注意 :+ 和格式之间没有空格

常用格式:

%F:完整日期格式,等价于%Y-%m-%d

%Y:年份

%m:月份

%d:按月计的日期

%T:时间,等于%H:%M:%S

%H: 小时,24小时制(00~23)

%M:分钟

%S:秒

[root@cx ~]# date -d "$(cat /proc/uptime | awk -F. '{print $1}') second ago"
2023年 05月 15日 星期一 20:18:49 CST
[root@cx ~]# date -d "$(cat /proc/uptime | awk -F. '{print $1}') second ago" +"%Y%m%d %H:%M:%S"
20230515 20:18:49
[root@cx ~]# date -d "$( awk -F. '{print $1}' /proc/uptime) second ago" +"%Y%m%d %H:%M:%S"
20230515 20:18:49

getline的使用

当getline左右无重定向符“<”或“|”时,awk首先读取到了第一行,就是1,然后getline,就得到了1下面的行,就是2,因为getline之后,awk会改变对应的NF,NR,FNR和$0等内部变量,所以此时的$0的值就不再是1,而是2了,即隔行输出。然后将它打印出来。
当getline左右有重定向符“<”或“|”时,getline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。

#当有重定向符号或 “|” 时,只会输出第1行
awk 'BEGIN {"cat a.txt" |getline; {print }}'
one
 
#当有重定向符号或 “|” 时,输出奇数行
cat a.txt | awk '{print $0;getline}'
one
three
five
seven
nine
eleven
#输出偶数行
cat a.txt | awk '{getline;print $0}'
two
four
six
eight
ten
twelve
[root@cx ~]# w
 20:49:50 up 31 min,  4 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     :0       :0               20:19   ?xdm?  29.01s  0.19s /usr/libexec/gnome-session-binary --ses
root     pts/0    :0               20:20   29:32   0.05s  0.05s bash
root     pts/1    192.168.47.1     20:20    6.00s  0.10s  0.00s w
root     pts/2    192.168.47.1     20:35    8:38   0.04s  0.04s -bash
[root@cx ~]# awk 'BEGIN{n=0;while("w" | getline) n++; {print n-2}}'
4

FNR:awk当前读取的记录数,其变量值小于等于NR(比如当读取第二个文件时,FNR是从0开始重新计数,而NR不会)。
NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件

 

awk数组

#BEGIN中的命令只执行一次
awk 'BEGIN{a[0]=1;a[1]=2;a[2]=3;print a[2]}'
3
#awk数组的下标除了数字,还可以使用字符串,字符串需要使用双引号
awk 'BEGIN{a["q"]="aaa";a["m"]="bbb";a["y"]="ccc";print a["q"]}'
aaa
 
awk 'BEGIN{a["q"]=1;a["m"]=2;a["y"]=3;for(i in a){print i,a[i]}}'
y 3
m 2
q 1
[root@cx ~]# awk 'BEGIN{a[0]=1;a[1]=2;a[2]=3;for(i in a){print i,a[i]}}'
0 1
1 2
2 3

过滤文本中重复行数

cat b.txt
aaa
bbb
ccc
aaa
aaa
aaa
bbb
bbb
ccc
#将文本的内容作为数组下标,a[$1]++表示出现相同的行,就自加1
awk '{a[$1]++}END{for (i in a){print i,a[i]}}' b.txt
aaa 4
ccc 2
bbb 3

过滤访问本机密码输入失败的命令

#过滤密码输出错误的IP地址及输入次数
[root@cx log]# awk '/Failed password/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure
192.168.47.10 2
192.168.47.100 3

#过滤输入次数大于4次的IP地址
[root@cx log]# awk '/Failed password/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure | awk '$2>2{print $1}'
192.168.47.100

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值