awk
2.2.4 优先级
简单实践
实践1-分结构实践
BEGIN设定数据处理的前置准备
[root@rocky9 ~]# awk 'BEGIN{OFS=":"} {print NR,$0}' awk.txt
1:nihao awk1 awk2 awk3
2:nihao awk4 awk5 awk6
3:nihao awk7 awk8 awk9
{}定制输出的内容样式
[root@rocky9 ~]# awk '{ print "第一列:"$1,"第二列:"$2 }' awk.txt
第一列:nihao 第二列:awk1
第一列:nihao 第二列:awk4
第一列:nihao 第二列:awk7
END设定信息处理完毕后的收尾动作
[root@rocky9 ~]# awk 'END{printf "----------------\n行数总计: %2d\n", NF}' awk.txt---------------
行数总计: 4
实践2-优先级演示
[root@rocky9 ~]# awk -F: 'BEGIN{print "begin中的NR值:" NR} NR==11 {print "命令中的
NR值: " NR}END{print "END中的NR值: " NR}' /etc/passwd
begin中的NR值:0
命令中的NR值: 11
END中的NR值: 23
结果可知:
begin的优先级 > 命令优先级 > END的优先级
实践3-组合演练
BEGIN 和 {} 实现信息的头部格式化
[root@rocky9 ~]# awk 'BEGIN{print "第一列\t第二列\n----------------"}{print
$1"\t"$2}' awk.txt
第一列 第二列---------------
nihao awk1
nihao awk4
nihao awk7
完全组合实现信息的头部和尾部格式化操作
[root@rocky9 ~]# awk 'BEGIN{print "第一列\t第二列\n----------------";total=0;}
{print $1"\t"$2;total = NR}END{printf "----------------\n行数总计: %2d\n", total}'
awk.txt
第一列 第二列---------------
nihao awk1
nihao awk4
nihao awk7---------------
行数总计: 3
统计文件格式化
[root@rocky9 ~]# awk -F":" 'BEGIN{printf "--------------------------
\n%-12s|%9s|\n---------------------------\n","用户名","shell类型"}{printf
"%-15s|%10s|\n---------------------------\n",$1,$7}END{printf "用户总数总: %2d\n",
NR}' passwd.txt--------------------------
用户名
| shell类型|--------------------------
root
| /bin/bash|--------------------------
用户总数总: 1
定制配置考试成果表
[root@ss test]# cat course_scores.txt
张三 100 56 99
李四 90 68 89
王五 50 78 67
赵六 80 99 89
格式化显示
[root@ss test]# awk 'BEGIN{printf "---------------------\n|%-3s|%2s|%2s|%2s|\n----------------------\n","姓名","语文","数学","历史";} NR>=1 {printf "|%-3s|%4d|%4d|%4d|\n",$1,$2,$3,$4} END{printf "----------------------\n学生 总数总: %2d\n", NR}' ./course_scores.txt
---------------------
|姓名 |语文|数学|历史|
----------------------
|张三 | 100| 56| 99|
|李四 | 90| 68| 89|
|王五 | 50| 78| 67|
|赵六 | 80| 99| 89|
----------------------
学生 总数总: 4
2.2.5 变量实践
简单实践
实践1-内置变量的进阶使用
NF 查看当前所在目录
[root@rocky9 ~]# echo $PWD | awk -F / '{print $NF}'
root
[root@rocky9 ~]# cd /etc/sysconfig/
[root@rocky9 /etc/sysconfig]# echo $PWD | awk -F / '{print $NF}'
sysconfig
查看文件名称
查看文件所在路径
[root@rocky9 ~]# echo /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F / '{print $NF}'
ifcfg-eth0
[root@rocky9 ~]# echo /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F / '{print $(NF-1)}'
network-scripts
实践2-NR行号的作用
快速获取ip地址
[root@rocky9 ~]# ifconfig eth0 | awk 'NR==2{print $2}'
10.0.0.12
[root@rocky9 ~]# ifconfig eth0 | awk '/netmask/{print $2}'
10.0.0.12
快速获取文件行数
[root@rocky9 ~]# awk -F: 'END{print NR}' /etc/passwd
23
[root@rocky9 ~]# awk -F: 'END{print NR}' /etc/sysconfig/network-scripts/ifcfg-eth0
20
实践3-FNR 和 FILENAME 获取文件基本信息
获取文件基本信息
[root@rocky9 ~]# awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release
1 /etc/issue \S
2 /etc/issue Kernel \r on an \m
3 /etc/issue
1 /etc/redhat-release CentOS Linux release 7.9.2009 (Core)
解析:
FNR 获取文件内容,同时在前面增加行号
FILENAME 获取文件名称
FIELDWIDTHS:重定义列宽并打印,注意不可以使用$0打印所有,因为$0是打印本行全内容,不会打印你定义的字段
[root@rocky9 ~]# awk 'BEGIN{FIELDWIDTHS="5 2 8"}NR==1{print $1,$2,$3}'
passwd.txt
root: x: 0:0:root
实践4-命令参数
ARGC 获取命令行参数的个数,包括awk命令
[root@rocky9 ~]# awk 'NR==1 {print ARGC }' awk.txt
2
ARGV:将命令行所有参数放到一个数组中,ARGV[下标] 获取所有参数
[root@rocky9 ~]# awk 'NR==1 {print ARGV[0] }' awk.txt
awk
[root@rocky9 ~]# awk 'NR==1 {print ARGV[1] }' awk.txt
awk.txt
实践5-自定义变量
变量实践
[root@rocky9 ~]# awk -v name='shuji' 'BEGIN{print name}'
shuji
[root@rocky9 ~]# awk 'BEGIN{name="shuji";print name}'
shuji
定制格式化输出
[root@rocky9 ~]# awk -F: '{age=36; address="beijing";print $1,age,address}' passwd.txt
root 36 beijing
2.2.6 赋值运算
实践1-字符串赋值
[root@rocky9 ~]# awk -v name='shuji' 'BEGIN{print name}'
shuji
[root@rocky9 ~]# awk 'BEGIN{school="xigongda";print school}'
xigongda
实践2-数据赋值
简单赋值 (=) 先接将右侧的值赋给左侧的变量
递增赋值 (+=) 变量的当前值与右侧的值相加,然后将结果赋回给该变量
递减赋值 (-=): 将变量的当前值与右侧的值相减,然后将结果赋回给该变量
前置递增 (++): 先将变量的值增加 1,然后返回新值
后置递增 (i++) 先返回变量的当前值,然后将变量的值增加 1
前置递减 (--) 先将变量的值减少 1,然后返回新值
后置递减 (i--) 先返回变量的当前值,然后将变量的值减少 1
命令区域段内进行数据赋值操作
[root@rocky9 ~]# echo | awk '{i=10;print i+=1}'
11
[root@rocky9 ~]# echo | awk '{i=10;print i++,i}'
10 11
[root@rocky9 ~]# echo | awk '{i=10;print ++i,i}'
11 11
[root@rocky9 ~]# echo | awk '{i=10;print --i,i}'
9 9
[root@rocky9 ~]# echo | awk '{i=10;print i--,i}'
10 9
在BEGIN段是可以的,由于END段主要是收尾的信息显示,所以基本不做计算层次的功能
[root@rocky9 ~]# awk 'BEGIN{i=0;print i++,i}'
0 1
[root@rocky9 ~]# awk 'BEGIN{i=0;print ++i,i}'
1 1
实践3-变量赋值-拓展【真假非】
-v 设定变量进行赋值操作
[root@rocky9 ~]# awk -v n=0 'n++' awk.txt
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
[root@rocky9 ~]# awk -v n=0 '!n++' awk.txt
nihao awk1 awk2 awk3
结果显示:-v n=0 在 awk 程序开始执行之前设置一个变量,并将其初始值设为 0。
n++ 是后增量操作
当 awk 开始处理第一行时,变量 n 的值为 0,因此 !n(即 !0)的值为 1
因为在逻辑上,0 被视为假,而 !0 则是真,即 1。因此,第一行会被打印出来。
当处理第二行时,由于 n++ 的操作,n 的值变为 1。此时,!n(即 !1)的值为 0(
因为在逻辑上,1 被视为真,而 !1 则是假,即 0。因此,第二行及之后的行不会被打印。
当递增与!同时存在的时候,!优先生效
实践4-数组赋值
在awk中可以设定数组
[root@rocky9 ~]# awk 'BEGIN{array[0]=100;print array[0]}'
100
2.2.8 逻辑运算
实践1-基本逻辑运算
与运算:真真为真,真假为假,假假为假
[root@rocky9 ~]# awk 'BEGIN{print 100>=2 && 100>=3 }'
1
[root@rocky9 ~]# awk 'BEGIN{print 100>=2 && 1>=100 }'
0
或运算:真真为真,真假为真,假假为假
[root@rocky9 ~]# awk 'BEGIN{print 100>=2 || 1>=100 }'
1
[root@rocky9 ~]# awk 'BEGIN{print 100>=200 || 1>=100 }'
0
注意:ubuntu24系统上,默认的awk版本是,mawk 1.3.4 20240123,有可能导致
root@ubuntu24:~# awk 'BEGIN{print 100>=2 && 100>=3 }'
awk: line 1: syntax error at or near =
解决办法:安装最新版本即可
root@ubuntu24:~# apt install gawk -y
实践2-文件逻辑运算
[root@rocky9 ~]# awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
root
python
[root@rocky9 ~]# awk -F: '$3==0 || $3>=1000 {print $1,$3}' /etc/passwd
root 0
python 1000
[root@rocky9 ~]# awk -F: '$3==0 && $3>=1000 {print $1,$3}' /etc/passwd
[root@rocky9 ~]# awk -F: '!($3<1000) {print $1,$3}' /etc/passwd
python 1000
[root@rocky9 ~]# awk -F: 'NR>=1&&NR<=2{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
实践3-非关系
[root@rocky9 ~]# awk 'BEGIN{print i}'
[root@rocky9 ~]# awk 'BEGIN{print !i}'
1
[root@rocky9 ~]# awk -v i=10 'BEGIN{print !i}'
0
[root@rocky9 ~]# awk -v i=-3 'BEGIN{print !i}'
0
[root@rocky9 ~]# awk -v i=0 'BEGIN{print !i}'
1
[root@rocky9 ~]# awk -v i=abc 'BEGIN{print !i}'
0
[root@rocky9 ~]# awk -v i='' 'BEGIN{print !i}'
1
2.2.9 匹配运算
实践1-真假值匹配
假值匹配
[root@rocky9 ~]# awk '"" {print $1,$3}' awk.txt
[root@rocky9 ~]# awk '0 {print $1,$3}' awk.txt
非零真值匹配
[root@rocky9 ~]# awk '"aaa" {print $1,$3}' awk.txt
nihao awk2
nihao awk5
nihao awk8
[root@rocky9 ~]# awk '9 {print $1,$3}' awk.txt
nihao awk2
nihao awk5
nihao awk8
[root@rocky9 ~]# awk -v n=8 'n{print $1,$3}' awk.txt
nihao awk2
nihao awk5
nihao awk8
实践2-内容匹配
内容匹配
[root@rocky9 ~]# awk -F ':' '$1 ~ "^ro" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@rocky9 ~]# awk -F ':' '$1 ~ "ftp" {print $0}' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@rocky9 ~]# awk -F ':' '$1 ~ "^[a-d].*" {print $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
dbus:x:81:81:System message bus:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
内容不匹配
[root@rocky9 ~]# awk -F ':' '$1 !~ "^ro" {print $0}' /etc/passwd
[root@rocky9 ~]# awk -F ':' '$1 !~ "^[a-r].*" {print $0}' /etc/passwd
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd
daemon:/dev/null:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
实践3-简单案例
准备不规则格式文件
[root@rocky9 ~]# cat zhengli.txt
http://www.sswang.org/index.html
http://www.sswang.org/1.html
http://api.sswang.org/index.html
asdfasdfsd
adfsdf
文件的规整
[root@rocky9 ~]# awk '/^[ \t]*/{print NR"--->"$1}' zhengli.txt
1--->http://www.sswang.org/index.html
2--->http://www.sswang.org/1.html
3--->http://api.sswang.org/index.html
4--->asdfasdfsd
5--->adfsdf
实践4-扩展实践
多值匹配打印
[root@rocky9 ~]# awk 'i=1;j=1{print $1,$3}' awk.txt
nihao awk1 awk2 awk3
nihao awk2
nihao awk4 awk5 awk6
nihao awk5
nihao awk7 awk8 awk9
nihao awk8
[root@rocky9 ~]# awk 'i=1{print $0};j=1{print $1,$3}' awk.txt
nihao awk1 awk2 awk3
nihao awk2
nihao awk4 awk5 awk6
nihao awk5
nihao awk7 awk8 awk9
nihao awk8
命令解析:
i=1;j=1{print $1,$3} 是两条命令
i=1; 虽然后面没有添加{},但是默认是 {print $0} 打印整行
假值匹配
[root@rocky9 ~]# awk '0' awk.txt
真值匹配
[root@rocky9 ~]# awk '!0' awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
非零真值匹配
[root@rocky9 ~]# awk '0-2' awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
零值匹配
[root@rocky9 ~]# awk '0-0' awk.txt
非零真值匹配
[root@rocky9 ~]# awk -v n=0 '++n' awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
3 正则表达式
3.1 基础实践
3.1.1 基础知识
通配符实践
创建基本环境
[root@rocky9 ~]# touch user-{1..3}.sh {a..d}.log
[root@rocky9 ~]# ls
a.log b.log d.log c.log
user-1.sh user-2.sh user-3.sh
*匹配任意字符
[root@rocky9 ~]# ls *.log
a.log b.log c.log d.log
[root@rocky9 ~]# ls u*
user-1.sh user-2.sh user-3.sh
?匹配一个字符
[root@rocky9 ~]# ls user?3*
user-3.sh
[]匹配中括号中的一个字符
[root@rocky9 ~]# ls user-[13]*
user-1.sh user-3.sh
3.1.2 字符匹配
简单实践
准备配置文件
[root@rocky9 ~]# cat keepalived.conf
! Configuration File for keepalived
global_defs {
router_id kpmaster
}
vrrp_instance VI_1 {
state MASTER
interface ens33
virtual_router_id 50
nopreempt
priority 100
advert_int 1
virtual_ipaddress {
192.168.8.100
}
}
实践1-单字符过滤
.过滤单个字符
[root@rocky9 ~]# grep 'st..e' keepalived.conf
state MASTER
[root@rocky9 ~]# grep 'ens..' keepalived.conf
interface ens33
实践2-范围单字符过滤
[] 过滤范围字符
[root@rocky9 ~]# grep 'i[a-z]t' keepalived.conf
interface ens33
virtual_router_id 50
advert_int 1
virtual_ipaddress {
[root@rocky9 ~]# grep 'i[a-n]t' keepalived.conf
interface ens33
advert_int 1
[root@rocky9 ~]# grep '[b-c]' keepalived.conf
global_defs {
vrrp_instance VI_1 {
interface ens33
[root@rocky9 ~]# egrep '[x-z]' keepalived.conf
priority 100
实践3-反向单字符过滤
只要包括的内容,都不要显示
[root@rocky9 ~]# grep '[^a-Z_ }{0-5]' keepalived.conf
! Configuration File for keepalived
192.168.8.100
实践4-过滤特定的字符范围
[root@rocky9 ~]# egrep 'state|priority' keepalived.conf
state MASTER
priority 100
[root@rocky9 ~]# egrep 'st|pri' keepalived.conf
router_id kpmaster
vrrp_instance VI_1 {
state MASTER
priority 100
3.1.3 锚定匹配
简单实践
准备实践文件
[root@rocky9 ~]# cat nginx.conf
#user nobody;
worker_processes 1;
http {
sendfile
on;
keepalive_timeout 65;
server {
listen
}
}
实践1-行首位地址匹配
行首位置匹配
[root@rocky9 ~]# grep '^wor' nginx.conf
worker_processes 1;
行尾位置匹配
[root@rocky9 ~]# grep 'st;$' nginx.conf
server_name localhost;
实践2-关键字匹配
关键字符串匹配
[root@rocky9 ~]# grep '^http {$' nginx.conf
http {
[root@rocky9 ~]# grep '^w.*;$' nginx.conf
worker_processes 1;
实践3-空行匹配
空行匹配
[root@rocky9 ~]# grep '^$' nginx.conf
[root@rocky9 ~]# grep '^[[:space:]]*$' nginx.conf
# 反向过滤空行
[root@rocky9 ~]# grep -v '^$' nginx.conf
#user nobody;
worker_processes 1;
http {
sendfile
on;
keepalive_timeout 65;
server {
listen
}
实践4-单词匹配
单词首部匹配
[root@rocky9 ~]# grep '\bloca' nginx.conf
server_name localhost;
location / {
[root@rocky9 ~]# grep '\<loca' nginx.conf
server_name localhost;
location / {
单词尾部匹配
[root@rocky9 ~]# grep 'ion\>' nginx.conf
location / {
[root@rocky9 ~]# grep 'ion\b' nginx.conf
location / {
单词内容匹配
[root@rocky9 ~]# grep '\<index\>' nginx.conf
index index.html index.htm;
[root@rocky9 ~]# grep '\<sendfile\>' nginx.conf
sendfile on;
3.1.4 分组符号
简单实践
准备配置文件
准备zookeeper的配置文件
[root@rocky9 ~]# cat zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/server/zookeeper/data
dataLogDir=/data/server/zookeeper/logs
clientPort=2181
server.1=10.0.0.12:2182:2183
server.2=10.0.0.13:2182:2183
server.3=10.0.0.14:2182:2183:observer
4lw.commands.whitelist=stat, ruok, conf, isro
实践1-分组信息匹配实践
获取zookeeper的集群相关信息
[root@rocky9 ~]# egrep '(server.[0-9])' zoo.cfg
server.1=10.0.0.12:2182:2183
server.2=10.0.0.13:2182:2183
server.3=10.0.0.14:2182:2183:observer
[root@rocky9 ~]# egrep '(init|sync)Limit' zoo.cfg
initLimit=10
syncLimit=5
实践2-信息的提取
借助于sed的编辑文件功能,实现特定信息的提取
[root@rocky9 ~]# grep server.1 zoo.cfg | sed -r "s/(.*)=(.*):(.*):(.*)/\1/"
server.1
[root@rocky9 ~]# grep server.1 zoo.cfg | sed -r "s/(.*)=(.*):(.*):(.*)/\2/"
10.0.0.12
[root@rocky9 ~]# grep server.1 zoo.cfg | sed -r "s/(.*)=(.*):(.*):(.*)/\3/"
2182
[root@rocky9 ~]# grep server.1 zoo.cfg | sed -r "s/(.*)=(.*):(.*):(.*)/\4/"
2183
解读:
sed 的 -r 选项指的是,后面的匹配是扩展正则的内容
3.2 进阶知识
3.2.1 限定符号
简单实践
准备文件
[root@rocky9 ~]# cat file.txt
ac
abbcd
abbbce
abbbbbc
abcf
实践1-精确匹配
精确匹配 以a开头 c结尾 中间是有b或者没有b 长度不限的字符串
[root@rocky9 ~]# egrep "^ab*c$" file.txt
ac
abbbbbc
精确匹配 以a开头 c结尾 中间只出现一次b或者没有b的字符串
[root@rocky9 ~]# egrep "^ab?c$" file.txt
ac
精确匹配 以a开头 中间是有b且至少出现一次 长度不限的字符串
[root@rocky9 ~]# egrep "^ab+" file.txt
abbcd
abbbce
abbbbbc
abcf
精确匹配 以a开头 中间是有b且至少出现两次最多出现四次 长度不限的字符串
[root@rocky9 ~]# egrep "^ab{2,4}" file.txt
abbcd
abbbce
abbbbbc
精确匹配 以a开头 中间是有b且正好出现三次的字符串
[root@rocky9 ~]# egrep "^ab{3}" file.txt
abbbce
abbbbbc
精确匹配 以a开头 中间是有b且至少出现两次的字符串
[root@rocky9 ~]# egrep "^ab{2,}" file.txt
abbcd
abbbce
abbbbbc
3.2.2 扩展符号
简单实践
准备文件
[root@rocky9 ~]# cat file1.txt
acd
abc
a_c
aZc
aZd
a c
a3c
精确匹配实践
c
以a开头c结尾 中间是A-Z任意字符 长度为三个字节的字符串
[root@rocky9 ~]# egrep "^a[[:upper:]]c$" file1.txt
aZc
以a开头c结尾 中间是可打印符号 长度为三个字节的字符串
[root@rocky9 ~]# egrep "^a[[:print:]]c$" file1.txt
abc
a_c
aZc
a c
a3c
以a开头c结尾 中间是符号字符 长度为三个字节的字符串
[root@rocky9 ~]# egrep "^a[[:punct:]]c$" file1.txt
a_c
以a开头c结尾 中间是空格或者TAB符字符 长度为三个字节的字符串
[root@rocky9 ~]# egrep "^a[[:blank:]]c$" file1.txt
a c
[root@rocky9 ~]# egrep "^a[[:space:]]c$" file1.txt
a c
以a开头c结尾 中间是十六进制字符 长度为三个字节的字符串
[root@rocky9 ~]# egrep "^a[[:xdigit:]]c$" file1.txt
abc
a3c
3.2.3 目标检测
ip检测
定制ip地址文件
[root@rocky9 ~]# cat testip.txt
112.456.44.55
256.18.56.1
10.0.0.12
匹配ip地址
[root@rocky9 ~]# egrep '(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]
{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([0-9]{1,2}|1[1-9]{2}|2[0-5][0-9]|25[0
4])$' testip.txt
10.0.0.12
网址检测
定制ip地址文件
[root@rocky9 ~]# cat testsite.txt
http://www.baidu.com
www.126.com
163.com
http.example.comcom
匹配ip地址
[root@rocky9 ~]# egrep '((http|https|ftp):\/\/)?(www\.)?([0-Z]+\.)([a-Z]{2,5})$'
testsite.txt
http://www.baidu.com
www.126.com
163.com
3.2.3 登录检测
手机号匹配
准备手机号文件
[root@rocky9 ~]# cat phone.txt
13412345678
135666666667
13a12345678
198123456
过滤真正的手机号
[root@rocky9 ~]# egrep '\<1[3-9][0-9]{9}\>' phone.txt
13412345678
邮箱地址匹配
定制邮箱地址文件
[root@rocky9 ~]# cat testemail.txt
[email protected]
[email protected]
10.0.0.12
"[email protected]
[email protected]
匹配邮箱地址
[root@rocky9 ~]# egrep "^[0-Z_]+\@[0-Z]+\.[0-Z]{2,5}$" testemail.txt
[email protected]
[email protected]