三剑客
  DcpJeOZ6VzTX 2023年11月02日 16 0

三剑客:grep 、awk 、sed

grep

作用:过滤内容的行

# grep过滤文件内容

( grep '[a-z]' 文件名 过滤出a-z所有字母、grep '[a-Z]'或 '[a-zA_Z]' 文件名 过滤出a-zA-Z的所有字母)

grep '关键字' 文件名(单引号不加也行)
^ 以某关键字开头
$ 以某关键字结尾
.* 匹配所有


# 选项
-E 过滤多个关键字,支持正则(关键字之间用|隔开,关键字|关键字)
-v 取反 显示除关键字之外的内容
-n 显示行号(grep -n 关键字 文件名 即可显示关键字所在行号)
-A 过滤关键字行的后行(-A2就是过滤关键字后2行)
-B 过滤关键字行的前行(-B3就是过滤关键字前3行)
-C 过滤关键字行的前后行(-C2就是过滤关键字前后2行)
-w 精准匹配,以单词为过滤(显示关键字及同行内容)
-o 只显示过滤内容(只显示关键字)
-i 不区分大小写 (例:grep 'd' 文件名 就会过滤出d和D)
-q 静默输出
-c 统计关键内容行数
-l 查看关键字在那个文件里,并输出关键字所在的文件名(grep -l nm 1.txt 2.txt)
-L 对比关键字不在那个文件中
-r 递归检索文件 (需要知道被改的内容是什么)grep -r '被改内容' ./ 即可打印出被改的文件名及路径
-h 只显示文件内容
-f 对比文件内容,只过滤出文件相同的内容
-vf 对比文件不同
-F 以列表形式列出有关键字的文件名及关键字
-m 列出含有关键字的前n行 (grep -m 10 'aaa' 文件名)
-x 只显示与关键字匹配完全符合的 (grep -x 'abc.123' 文件名)
# 选项用法
-n 过滤内容并标注行号
   [root@web02 web02]# grep -n '666' 1.txt
   1:1,wyd,666
   [root@web02 web02]# grep -n '77' 1.txt
   2:2,hhh,777
   [root@web02 web02]# grep -n 'wb' 1.txt
   3:3,wb,888
   [root@web02 web02]# grep -n 'zdp' 1.txt
   4:4,zdp,999
-A 过滤内容后N行
   [root@web02 web02]# grep -A 2 '666' 1.txt
   1,wyd,666
   2,hhh,777
   3,wb,888
-B 过滤内容前N行
   [root@web02 web02]# grep -B 2 '999' 1.txt
   2,hhh,777
   3,wb,888
   4,zdp,999
-C 过滤内容前后N行
   [root@web02 web02]# grep -C 1 '888' 1.txt
   2,hhh,777
   3,wb,888
   4,zdp,999
-w 精致匹配
   [root@web02 web02]# ifconfig | grep -w inet
   inet 10.0.0.8 netmask 255.255.255.0 broadcast 10.0.0.255
   inet 127.0.0.1 netmask 255.0.0.0
   # 区别!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   [root@web02 web02]# ifconfig | grep inet
   inet 10.0.0.8 netmask 255.255.255.0 broadcast 10.0.0.255
   inet6 fe80::20c:29ff:fe09:a01f prefixlen 64 scopeid 0x20<link>
   inet 127.0.0.1 netmask 255.0.0.0
   inet6 ::1 prefixlen 128 scopeid 0x10<host>
-o 只打印关键字
   [root@web02 web02]# ifconfig | grep -o inetinet
   inet
   inet
   inet
   inet
-v 取反
   [root@web02 web02]# ifconfig | grep -v inet
   eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
   ether 00:0c:29:09:a0:1f txqueuelen 1000 (Ethernet)
   RX packets 225285 bytes 107040095 (102.0 MiB)
   RX errors 0 dropped 0 overruns 0 frame 0
   TX packets 124492 bytes 28950368 (27.6 MiB)
   TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
   eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
   ether 00:0c:29:09:a0:29 txqueuelen 1000 (Ethernet)
   RX packets 247 bytes 41447 (40.4 KiB)
   RX errors 0 dropped 0 overruns 0 frame 0
   TX packets 2708 bytes 458343 (447.6 KiB)
   TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
   lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
   loop txqueuelen 1000 (Local Loopback)
   RX packets 57 bytes 9842 (9.6 KiB)
   RX errors 0 dropped 0 overruns 0 frame 0
   TX packets 57 bytes 9842 (9.6 KiB)
   TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
-i 忽略大小写
   [root@web02 web02]# grep nb 2.txt
   nb
   [root@web02 web02]# grep NB 2.txt
   NB
   NB!!!
   [root@web02 web02]# grep -i nb 2.txt
   nb
   NB
   NB!!!
-q 静默输出
   [root@web02 web02]# grep -i nb 2.txt
   nb
   NB
   NB!!!
   [root@web02 web02]# grep -iq nb 2.txt
-c 统计过滤内容的行数
   [root@web02 web02]# cat 2.txt | grep -c nb
   1 
   [root@web02 web02]# cat 2.txt | grep -c NB
   2
-l 对比关键子在那个文件中
   [root@web02 web02]# grep -l nb 1.sh tb.sh 1.txt 2.txt
   2.txt
-L 对比关键字不在那个文件之中
   [root@web02 web02]# grep -L nb 1.sh tb.sh 1.txt 2.txt
   1.sh
   tb.sh
   1.txt
-r 递归检索文件

-h 只显示文件内容

-f 只显示文件相同内容
   [root@web02 web02]# grep -f 3.txt 4.txt
   123
   456
   789
   [root@web02 web02]# grep -vf 3.txt 4.txt
   321
-F 带关键字的内容列表形式展开
   [root@web02 web02]# grep -F '1' 1.txt 2.txt 3.txt 1.sh
   1.txt:1,wyd,666
   3.txt:123
   4.txt:123
   1.sh:lb01=10.0.0.5

-m 列出含有关键字的前n行(加 -m 只显示关键字行,直接 -num 显示关键字前后各n行)
   [root@web02 web02]# grep -6 'root' /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
   sync:x:5:0:sync:/sbin:/bin/sync
   shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
   `root:x:0:0:root:/root:/bin/bash
   dbus:x:81:81:System message bus:/:/sbin/nologin
   polkitd:x:999:998:User for polkitd:/:/sbin/nologin
   sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
   postfix:x:89:89::/var/spool/postfix:/sbin/nologin
   rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
   rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin

-x 只匹配全部关键字的行
   rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
   [root@web02 web02]# grep -x 'rpc:x:32:32:Rpcbind
   Daemon:/var/lib/rpcbind:/sbin/nologin' /etc/passwd
   rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin

-E (过滤多个内容)支持正则
   [root@web02 web02]# grep -E 'root|mysql' /etc/passwd
   root:x:0:0:root:/root:/bin/bash
   operator:x:11:0:operator:/root:/sbin/nologin
   mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
   [root@web02 web02]# grep 'root|mysql' /etc/passwd

sed

sed针对的核心内容:增、删、改、查

sed命令的执行流程

1.sed先是按行读取文件内容 2.每读取一行内容,都会进行一次判断,是不是你想要的行 3.如果不是,则判断是不是加了-n选项 4.如果加了-n,就读取下一行 5.如果没加-n,就会将所有内容输出到命令行(默认输出) 6.如果是,你想要的那一行(第三行)则判断执行的后续动作(p d s a i c) 7.动作处理完成后,输出指定的内容 8.即便是读取完了,内容也输出了,sed也会继续往后读,直到文件的最后一行

-n 匹配你要的内容 不加-n 匹配你要的内容和全部内容

sed 查

`p print打印/显示

# 加-n 只打印想要的行,不加-n,打印想要的行及所有行
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
3,wb,888
4,zd,999

##加-n(取消默认输出)
[root@web01 ~]# sed -n '3p' 1.test
3,wb,888

##不加-n
[root@web01 ~]# sed '3p' 1.test 
1,wy,666
2,hh,777
3,wb,888
3,wb,888
3,wb,888
4,zd,999

##打印多行
##打印第一行和第三行
[root@web01 ~]# sed -n '1p;3p' 1.test
1,wyd,666
3,wb,888

##打印一到三行
[root@web01 ~]# sed -n '1,3p' 1.test
1,wy,666
2,hh,777
3,wb,888


`# sed 模糊查询
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999

[root@web01 ~]# sed -n '/wy/p' 1.test
1,wy,666
[root@web01 ~]# sed -n '/6/p' 1.test
1,wy,666
[root@web01 ~]# sed -n '/,/p' 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999

# -nr 查找多个
[root@web01 ~]# sed -nr '/wb|wy/p' 1.test
1,wy666
3,wb,888
[root@web01 ~]# sed -nr '/wb|wy|hh/p' 1.test
1,wyd,666
2,hhh,777
3,wb,888
[root@web01 ~]# sed -nr '/wb|wy|,/p' 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999


# 范围模糊查找(wy到wb)
[root@web01 ~]# sed -nr '/wy/,/wb/p' 1.test
1,wy,666
2,hh,777
3,wb,888

`# sed模拟grep -A (过滤关键字及其后nim行)
[root@web01 ~]# sed -n '/hh/,+2p' 1.test
2,hh,777
3,wb,888
4,zd,999

`# 过滤从关键字开始到第num行
[root@web01 ~]# sed -n '/hh/,4p' 1.test
2,hh,777
3,wb,888
4,zd,999

`# 模拟seq`
[root@web01 ~]# seq 1 2 10
1
3
5
7
9
[root@web01 ~]# sed -n '1~2p' 1.test
1,wy,666
3,wb,888

`# 取反`
[root@web01 ~]# sed -n '/wy/!p' 1.test
2,hh,777
3,wb,888
4,zd,999

sed删

`d delete
# 临时删除
[root@web01 ~]# sed '2d' 1.test
1,wy,666
3,wb,888
4,zd,999
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999

# 永久删除(-i)
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
[root@web01 ~]# sed -i '2d' 1.test
[root@web01 ~]# cat 1.test
1,wy,666
3,wb,888
4,zd,999

# 删除第一行
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
[root@web01 ~]# sed '1d' 1.test
2,hh,777
3,wb,888
4,zd,999

# 删除最后一行
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
[root@web01 ~]# sed '$d' 1.test
1,wy,666
2,hh,777
3,wb,888

# 删除某个范围(例hhh到最后一行)
[root@web02 web02]# sed '/hh/,$d' 1.txt
1,wy,666
[root@web02 web02]# sed '1!d' 1.txt
1,wy,666

# 删除多个(删除wb到msx的行)
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000
[root@web01 ~]# sed '/wb/,/ms/d' 1.test
1,wy,666
2,hh,777

# 删除多个(删除第三行和第五行)(临时删)
[root@web01 ~]# sed '3d;5d' 1.test
1,wy,666
2,hh,777
4,zd,999
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000

sed增

cai

`a append 在下一行追加
# 在第二行下面追加*,lj,111
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000
[root@web01 ~]# sed '2a*,lj,111' 1.test
1,wy,666
2,hh,777
*,lj,111
3,wb,888
4,zd,999
5,ms,000

`i insert 在前面插入
# 在最后一行上面插入6*,zhy,222
[root@web01 ~]# sed '$i6*,zhy,222' 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
6*,zhy,222
5,ms,000
# 在第三行上面插入7*,zhy,222
[root@web01 ~]# sed '3i7*,zhy,222' 1.test
1,wy,666
2,hh,777
7*,zhy,222
3,wb,888
4,zd,999
5,ms,000


`c replace 替换整行
# 把第三行替换成0,000,000
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000
[root@web01 ~]# sed '3c0,000,000' 1.test
1,wy,666
2,hh,777
0,000,000
4,zd,999
5,ms,000
替换最后一行就是sed '$c000,000,000' 1.test

sed改

s substitute 替换
g global 全局

s###g  ##末行模式替换用:%s###g
s///g
s@@@g

# 把wy替换成ww
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000
[root@web01 ~]# cat 1.test | sed s#wy#ww#g
1,ww,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000

# 正则
[root@web01 ~]# cat 1.test | sed 's#[0-9]#666#g'
666,wy,666666666
666,hh,666666666
666,wb,666666666
666,zd,666666666
666,ms,666666666
[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000

练习 用sed截取内网IP

# 用sed截取内网IP

[root@web01 ~]# ifconfig eth0 | sed -nr 's#^.*inet (.*)  net.*$#\1#gp'
10.0.0.7
[root@web01 ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.7  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe64:6a35  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:64:6a:35  txqueuelen 1000  (Ethernet)
        RX packets 130475  bytes 52913678 (50.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 73376  bytes 14765349 (14.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


## 解析

inet 10.0.0.7  netmask 255.255.255.0  broadcast 10.0.0.255

ifconfig eth0 | sed -nr 's#^.*inet (.*)  net.*$#\1#gp'

-nr 查找
s###g 替换

^.*inet 匹配inet及开头所有  (inet )
  ^ 以开头的所有
  .*inet 匹配inet

(.*) 要截取的IP,做后项引用   (10.0.0.7)

net.*$ 匹配net及结尾所有      (netmask 255.255.255.0  broadcast 10.0.0.255)
  net.* 匹配net
  $ 以结尾的所有

\1 后项引用

p 打印


# 其他方法
ifconfig | sed -n '2p'|sed -nE 's/.*inet ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/p'

ifconfig eth0 | sed -n 's/.*inet \([^ ]*\).*/\1/p'

sed模式空间

`换行符\n

# 换行符替换成空格
[root@web01 ~]# sed 'N;s#\n# #g' 1.test
1,wy,666 2,hh,777
3,wb,888 4,zd,999
5,ms,000


# N;
[root@web01 ~]# sed 'N;N;N;N;s#\n# #g' 1.test
1,wy,666 2,hh,777 3,wb,888 4,zd,999 5,ms,000

`sed模式空间
# :label;N;      ;t label
[root@web01 ~]# sed ':label;N;s#\n# #g;t label' 1.test
1,wy,666 2,hh,777 3,wb,888 4,zd,999 5,ms,000

awk

awk 不是一个命令,是一门语言,也能做for循环,awk有单双引之分

awk又叫GNU awk,gawk

[root@web01 ~]# which awk
/usr/bin/awk
[root@web01 ~]# ls -l `which awk`
lrwxrwxrwx. 1 root root 4 Apr 12 11:11 /usr/bin/awk -> gawk
'' 输出变量
"" 输出字符串
awk输出变量用单引 bash输出变量""

平时我们使用,都是当做命令使用,所以我们称之为 单行脚本 那么awk能不能写脚本呢,必然可以,在linux系统中就有很多的jawk脚本

[root@zabbix01 ~]# find /usr/share/ -type f -name '*.awk'
/usr/share/awk/assert.awk
/usr/share/awk/bits2str.awk
/usr/share/awk/cliff_rand.awk
/usr/share/awk/ctime.awk
/usr/share/awk/ftrans.awk
/usr/share/awk/getopt.awk
/usr/share/awk/gettime.awk
/usr/share/awk/group.awk
/usr/share/awk/join.awk
/usr/share/awk/libintl.awk
/usr/share/awk/noassign.awk
/usr/share/awk/ord.awk
/usr/share/awk/passwd.awk
/usr/share/awk/quicksort.awk
/usr/share/awk/readable.awk
/usr/share/awk/rewind.awk
/usr/share/awk/round.awk
/usr/share/awk/strtonum.awk
/usr/share/awk/walkarray.awk
/usr/share/awk/zerofile.awk

awk执行流程

awk读取文件内容之前 1.读取文件之前,先看命令的选项,例如 -F,-v (F指定为分隔符,V是赋予变量) 2.如果写了BEGIN{}则先在BEGIN{}中的指令

awk读取文件内容之时 1.awk在读取文件时,也是一行一行的读 2.读取一行之后,判断是否满足条件,如果是,则执行{对应动作} {print $1} awk -F , {print $1} 1.txt 3.如果不满足条件,awk继续读取下一行,直到满足条件或者到文件的最后一行

awk读取文件内容之后 1.所有文件读取完成之后,走END{}中的指令

读取文件之前
BEGIN{}

读取文件时
{}

读取文件之后
NED{}

# 读取文件时{}
[root@web01 ~]# awk '{print 1+2}'
^C
[root@web01 ~]# awk '{print 1+2}' 1.test
3
3
3
3
3

# 读取文件之前BEGIN{}
[root@web01 ~]# awk 'BEGIN{print 1+2}'
3

# 读取文件之后END{}
[root@web01 ~]# awk 'END{print 1+2}'
^C
[root@web01 ~]# awk 'END{print 1+2}' 1.test
3

awk的行和列

行 记录 record
列 字段 field

awk的取行

取行——取记录
`NR
number of record

# 取第一行
NR==1
[root@web02 web02]# awk 'NR==1' /etc/passwd
root:x:0:0:root:/root:/bin/bash

# 取一到三行
[root@web02 web02]# awk 'NR==1,NR==3' /etc/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

[root@web01 ~]# awk 'NR<=3' /etc/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



# sed 从第三行到最后一行
sed -n '3,$p'
# awk 从第三行到最后一行
[root@web02 web02]# awk 'NR>=3' /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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
………………
………………
xxx:x:1000:1000::/home/xxx:/bin/bash
yys:x:1001:1001::/home/yys:/bin/bash
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
xyz:x:1002:1002::/home/xyz:/bin/bash


`# awk的控制结束标语
awk -vRS= 是指定换行符
例: (以逗号为换行符: -vRS=,) (以点为换行符: vRS=.)
# 以,(逗号)为换行符 默认是以回车为分割符
[root@web02 web02]# cat 1.txt
1,wy,666
2.hh.777
3,wb,888
4.zd.999
5,ms,000
[root@web02 web02]# awk -vRS=, "NR==2" 1.txt
wy
[root@web02 web02]# awk -vRS=, "NR==3" 1.txt
666
2.hh.777
3 
[root@web02 web02]# awk -vRS=, "NR==4" 1.txt
wb
[root@web02 web02]# awk -vRS=, "NR==5" 1.txt
888
4.zd.999
5


[root@web01 ~]# awk -vRS=, '{print "这里是行号:"NR,"这里是每一行的内容:"$0}' 1.test
这里是行号:1 这里是每一行的内容:1
这里是行号:2 这里是每一行的内容:wy
这里是行号:3 这里是每一行的内容:666
2
这里是行号:4 这里是每一行的内容:hh
这里是行号:5 这里是每一行的内容:777
3
这里是行号:6 这里是每一行的内容:wb
这里是行号:7 这里是每一行的内容:888
4
这里是行号:8 这里是每一行的内容:zd
这里是行号:9 这里是每一行的内容:999
5
这里是行号:10 这里是每一行的内容:ms
这里是行号:11 这里是每一行的内容:000

[root@web01 ~]# cat 1.test
1,wy,666
2,hh,777
3,wb,888
4,zd,999
5,ms,000

awk的取列

取列——取字段
-vFS=: <==> -F:
FS 列分隔符
$数字 或 $内容(多个用,隔开)

# 每一行有多少列   字段(列)
NF== $number of field

FS: 内置变量 列分隔符 -F: = -vFS=:

# 打印出第一列和最后一列
[root@web02 web02]# awk -vFS=: '{print $1,$NF}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin

# 用#隔开第一列与第二列与……与第五列
[root@web02 web02]# awk -F: '{print $1"#"$2"#"$3"#"$4"#"$5}' /etc/passwd
root#x#0#0#root
bin#x#1#1#bin
daemon#x#2#2#daemon
adm#x#3#4#adm
lp#x#4#7#lp
sync#x#5#0#sync
shutdown#x#6#0#shutdown
halt#x#7#0#halt
mail#x#8#12#mail
operator#x#11#0#operator
games#x#12#100#games
ftp#x#14#50#FTP User


# 修改输出后的内容分隔符
-vOFS=

-vOFS=#
[root@web01 ~]# awk -F: -vOFS=# '{print $1,$2,$3,$4,$5}' /etc/passwd
root#x#0#0#root
bin#x#1#1#bin
daemon#x#2#2#daemon
adm#x#3#4#adm
lp#x#4#7#lp
sync#x#5#0#sync
shutdown#x#6#0#shutdown
halt#x#7#0#halt
mail#x#8#12#mail
operator#x#11#0#operator
games#x#12#100#games
ftp#x#14#50#FTP User
nobody#x#99#99#Nobody


[root@web02 web02]# awk -F: -vOFS=\| '{print $1,$2,$3,$4,$5,$6,$7}' /etc/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
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
operator|x|11|0|operator|/root|/sbin/nologin
games|x|12|100|games|/usr/games|/sbin/nologin
ftp|x|14|50|FTP User|/var/ftp|/sbin/nologin

[root@web01 ~]# awk -F: -vOFS=\& '{print $1,$2,$3,$4,$5}' /etc/passwd
root&x&0&0&root
bin&x&1&1&bin
daemon&x&2&2&daemon
adm&x&3&4&adm
lp&x&4&7&lp
sync&x&5&0&sync
shutdown&x&6&0&shutdown
halt&x&7&0&halt
mail&x&8&12&mail
operator&x&11&0&operator
games&x&12&100&games
ftp&x&14&50&FTP User
nobody&x&99&99&Nobody

截取top时间/截取IP

[root@web01 ~]# top
top - 10:15:05 up  1:40,  2 users,  load average: 0.06, 0.03, 0.05
Tasks:  91 total,   2 running,  89 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :   995892 total,   742740 free,   124532 used,   128620 buff/cache
KiB Swap:  1048572 total,  1048572 free,        0 used.   719416 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                 
     1 root      20   0  125288   3728   2568 S  0.0  0.4   0:01.70 systemd                                                                 
     2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd                                                                
     3 root      20   0       0      0      0 S  0.0  0.0   0:00.24 ksoftirqd/0                                                             
    19 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 bioset                                                                  
    20 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 bioset           

top -n1 是让他停止跳动
## 截取top时间
top -n1 | awk 'NR==1{print $3}'
## 截取top的TIME+
[root@web02 web02]# top -n1 | awk 'NR>=7{print $12}'
TIME+
0:08.99
0:00.06
0:11.940:00.00
0:00.00
0:00.00
0:08.82
0:00.00
0:03.21
0:00.00
0:00.00


# 截取IP                      匹配范围/IPADDR/
[root@web02 web02]# awk -F= '/IPADDR/{print $2}' /etc/sysconfig/networkscripts/ifcfg-eth0 | awk -F '"' '{print $2}'
10.0.0.8

[root@web02 ~]# awk -F'[= "]+' '/IPADDR/{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0
10.0.0.8

一个完整的awk

#一个完整的awk

[root@web01 ~]# awk -F: 'BEGIN{print "name","uid"}{print $1,$3}END{print "文件处理完成"}' /etc/passwd |column -t
name             uid
root             0
bin              1
daemon           2
adm              3
lp               4
sync             5
shutdown         6
halt             7
mail             8
operator         11
games            12
ftp              14
nobody           99
systemd-network  192
dbus             81
polkitd          999
sshd             74
postfix          89
ntp              38
nginx            998
xxx              1000
文件处理完成


## 解析
-F :  以:为分隔符
BEGIN{print "name","uid"}  读取文件之前,先打印出name 和 uid
{print $1,$3}  读取文件时打印出文件的第一列和第三列
END{print "文件处理完成"}  读取文件之后打印‘件处理完成’
column -t  为了美观对齐

awk的模式与动作

模式

在awk中到底有哪些可以被看做是模式的呢?

  • 正则表达式
# 正则表达式写法
'/正则表达式/flag'
'$1~/正则表达式/flag'
'$1!~/正则表达式/flag'
只不过我们在awk中很少使用flag
  • 比较表达式
NR==1
NR>=10
NR<=100
NR>=1 && NR<=10
$1>=100
  • 范围模式
## 精确匹配行号:从第10行到第20行
NR==10,NR==20 (NR>=10&&NR<=20)
## 精确匹配字符串:从该字符串的行到另一个字符串所在行
'/root/,/wxk/'
'/从哪个字符串所在行/,/到那个字符串所在行/' #中间的行都包含进去
## 模糊匹配字符串:从含有该字符串所在行到含有另一字符串所在行
'$1~/oo/,$1~//
动作

动作 在awk中,我们最常用的动作就是 print 当然我们还有别的动作可以使用: print打印 gsub替换 变量赋值 统计计算 BEGIN模式 如果要使用BEGIN模式,那么一定要成双成对的出现:{} 那么我们要知道,BEGIN{}中,大括号里面的内容,会在读取文件内容之前执行 主要应用场景:

  • 1.统计或计算
[root@zabbix01 ~]# awk 'BEGIN{print 1/3}'
0.333333
  • 2.awk功能测试
  • 3.输出表格的表头

END模式 一般来说,END{}要比BEGIN{}重要一些,BEGIN{}可有可无,计算其实可以放在读取文件的时候,也可以执行 END{}中,大括号里面的内容,会在awk读取完文件的最后一行后,进行处理 作用:一般我们使用END{}来显示对日志内容分析后的一个结果 当然,还有其他功能,比如文件读取完了,可以显示一些尾部信息

# 1.统计/etc/service文件中一共有多少行
## 分析:
## 条件:无
## 动作:读一行就加1 {i++}
[root@zabbix01 ~]# awk '{i++;print i}' /etc/services
#这么写是读一行会加一次,读一行会加一次,把整个过程都显示出来了。#我么现在只需要显示一个结果,所以我们需要把print放到END{}中
## 传统写法
[root@zabbix01 ~]# awk '{i++}END{print i}' /etc/services
11176
## 流氓写法
[root@zabbix01 ~]# sed -n '$=' /etc/services
11176
# 2.统计/etc/service中空行的数量
[root@zabbix01 ~]# awk '/^$/{i++}END{print i}' /etc/services
17
# 3.统计出下列文件中所有人的年龄和
[root@zabbix01 ~]# vim student.txt
姓名 年龄
呜呜呜 23
咕咕咕 18
嘿嘿嘿 99
[root@zabbix01 ~]# awk 'NR>1{i=i+$2}END{print i}' student.txt
140
[root@zabbix01 ~]# awk 'NR>1{i+=$2}END{print i}' student.txt
140
# 4.统计nginx日志中,状态码是200的次数以及,状态码是200时占用的流量
条件:
- 获取状态码 $9
- 获取大小 /流量 $10
## 获取条件
awk '$10==200' blog.aaa.com_access.log
## 执行动作
awk '$10==200{i++;count=count+$11}END{print i,count}'
blog.aaa.com_access.log
848 112743579
# 美化
awk '$10==200{i++;count=count+$11}END{print "正常状态码次数:"i,"总流量(字节):"count}'
blog.aaa.com_access.log
正常状态码次数:848 总流量(字节):112743579
## 脚本写法
awk '
$10==200{
i++;
count=count+$11
} E
ND{
print "正常状态码次数:"i,"总流量(字节):"count
}' blog.aaa.c_access.log
# 5.统计nginx日志中状态码是4xx和5xx的次数及总流量

条件:以4,5开头
动作:统计总流量
awk '$10~/^[45]/{i++;count+=$11}END{print i,count}'
blog.aaa.com_access.log
## 那么2xx的3xx的
awk '$10~/^2/{i++;count+=$11}END{print i,count}' blog.aaa.com_access.log
awk '$10~/^3/{i++;count+=$11}END{print i,count}' blog.aaa.com_access.log
# 6.综合应用:分别统计每种状态码的总流量
## 最简单的写法
awk '
$10~/^2/{i2++;count2+=$11}
$10~/^3/{i3++;count3+=$11}
$10~/^4/{i4++;count4+=$11}
$10~/^5/{i5++;count5+=$11}
END{
print "2xx状态码:",i2,count2
print "3xx状态码:",i3,count3
print "4xx状态码:",i4,count4
print "5xx状态码:",i5,count5
}' blog.aaa.com_access.log
### 注意:这种方式并不好,所以我们需要使用awk更牛的方法来统计不同分类的,比如统计IP,统计URI就没有

数组

赋值

awk 'BEGIN{array[0]="wyd";array[1]='hhh'}'

取值

awk 'BEGIN{array[0]="wyd";array[1]="hhh";print array[0],array[1]}'
会出来0和1 加个array[name]就会出来wyd和hhh

数组

# 会出来0和1 加个array[name]就会出来w和hh

[root@web02 web02]# awk 'BEGIN{array[0]="w0d";array[1]="l2f";for(name in array){print name}}'
0 1 
[root@web02 web02]# awk 'BEGIN{array[0]="w0d";array[1]="l2f";for(name in array){print array[name]}}'
w0d
l2f

#1.取出下列域名并根据域名,进行统计排序处理
https://blog.aaa.com/index.html
https://blog.aaa.com/1.html
http://post.aaa.com/index.html
http://mp3.aaa.com/index.html
https://blog.aaa.com/3.html
http://post.aaa.com/2.html
## 在awk中,我们给数组赋值,肯定不能像上面那样赋值
#正确赋值方式:
array[]++
# 让数组的下标自增,然后在中括号中写入要统计的内容
array[域名所在列]++
array[$3]++ #当然这个$3是以/为分隔符
[root@zabbix01 ~]# awk -F/ '{url[$3]++}END{for(n in url){print n,url[n]}}'
url.txt
blog.aaa.com 3
post.aaa.com 2
mp3.aaa.com 1

#2.统计nginx日志中,每个IP访问使用的流量总和
条件:无
动作:统计IP及流量总和 array[$1]=array[$1]+$11 可以写成ip[$1]+=$11
awk '{array[$1]+=$11}END{for(ip in array){print ip,array[ip]}}'
blog.aaa.com_access.log

#3.每个IP出现的次数及使用的流量
条件:无
动作:
1.统计ip的次数:count[$1]++
2.流量总和:sum[$1]+=$11
awk '{count[$1]++;num[$1]+=$11}END{for(ip in count){print
ip,count[ip],num[ip]}}' blog.aaa.com_access.log

awk判断-if

#1.单分支判断
if($1~/root/){
	print $1,$2
} 

#2.双分支判断
if(){

}else{

} 
if(){

}else if(){

}else{

}

awk循环-for

#数组专用循环
for(n in array){
	print n,array[n]
} 
#通用循环
for(i=1;i<10;i++){
	print i
}
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  jnZtF7Co41Wg   2023年12月06日   10   0   0 sedlinux数据
  uvM09mQNI0hF   2023年11月19日   18   0   0 sedshell字符串
  eHipUjOuzYYH   2023年12月06日   13   0   0 sedbootstrapIPV6
  xIUntf9oR6GI   2023年11月28日   12   0   0 sedvim基础命令
  oIa1edJoFmXP   2023年11月24日   13   0   0 AppsedVue