awk经典实战、正则表达式

目录

1.筛选给定时间范围内的日志

2.统计独立IP

案列

需求

代码

运行结果

3.根据某字段去重

案例

运行结果

4.正则表达式

1)认识正则

2)匹配字符

3)匹配次数

4)位置锚定:定位出现的位置

5)分组和后向引用


1.筛选给定时间范围内的日志

grep/sed/awk用正则去筛选日志时,如果要精确到小时、分钟、秒,则非常难以实现。

但是awk提供了mktime()函数,它可以将时间转换成epoch时间值。

root@Ubuntu:~# # 2019-11-10 03:42:40转换成epoch为1970-01-01 00:00:00

root@Ubuntu:~# awk 'BEGIN{print mktime("2023 08 05 08 44 40")}'

1691196280

借此,可以取得日志中的时间字符串部分,再将它们的年、月、日、时、分、秒都取出来,然后放入mktime()构建成对应的epoch值。因为epoch值是数值,所以可以比较大小,从而决定时间的大小。

下面strptime1()实现的是将2023-08-04-12-40-40 29T03:42:40+08:00格式的字符串转换成epoch值,然后和which_time比较大小即可筛选出精确到秒的日志。

可以利用patsplit来取时间中的数字

root@Ubuntu:~# vim demo.awk

root@Ubuntu:~# cat demo.awk

BEGIN{

#要筛选什么时间的日志,将其时间构建成epoch值

which_time = mktime("2023 08 04 22 40 29")

}

{

#取出日志的日期时间字符串部分

#match($0,"^.*\\(.\*)\\\\.*",arr)

#将日期时间字符串转换为epoch值

tmp_time = strptime1(arr1)

#通过比较epoch值来比较时间大小

if(tmp_time > wgich_time){print}

}

#构建的时间字符串格式为:"2023-08-04T12:40:40+08:00"

function strptime1(str ,arr,Y,M,D,H,m,S){

patsplit(str,arr,"0-9{1,4}")

Y=arr1

M=arr2

D=arr3

H=arr4

m=arr5

S=srr6

return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))

}

下面strptime2()实现的是将10/Nov/2023:23:53:44+08:00格式的字符串转换成epoch值,然后和which_time比较大小即可筛选出精确到秒的日志。

root@Ubuntu:~# vim dwmo.awk

root@Ubuntu:~# cat dwmo.awk

BEGIN{

要筛选什么时间的日志,将其时间构建成epoch值

which_time = mktime("2023 08 04 11 42 40")

}

{

取出日志中的日期时间字符串部分

match($0,"^.*\\(.\*)\\\\.*",arr)

将日期时间字符串转换为epoch值

tmp_time = strptime2(arr1)

通过比较epoch值来比较时间大小

if(tmp_time > which_time){

print

}

}

构建的时间字符串格式为:"10/Nov/2023:23:53:44+08:00"

function strptime2(str,dt_str,arr,Y,M,D,H,m,S) {

dt_str = gensub("/:+"," ","g",str)

dt_sr = "10 Nov 2023 23 53 44 08 00"

split(dt_str,arr," ")

Y=arr3

M=mon_map(arr2)

D=arr1

H=arr4

m=arr5

S=arr6

return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))

}

function mon_map(str,mons){

mons"Jan"=1

mons"Feb"=2

mons"Mar"=3

mons"Apr"=4

mons"May"=5

mons"Jun"=6

mons"Jul"=7

mons"Aug"=8

mons"Sep"=9

mons"Oct"=10

mons"Nov"=11

mons"Dec"=12

return monsstr

}

2.统计独立IP

? url 访问IP 访问时间 访问人

案列

a.com.cn|202.109.134.23|2015-11-20 20:34:43|guest

b.com.cn|202.109.134.23|2015-11-20 20:34:48|guest

c.com.cn|202.109.134.24|2015-11-20 20:34:48|guest

a.com.cn|202.109.134.23|2015-11-20 20:34:43|guest

a.com.cn|202.109.134.24|2015-11-20 20:34:43|guest

b.com.cn|202.109.134.25|2015-11-20 20:34:48|guest

需求

统计每个URL的独立访问IP有多少个(去重),并且要为每个URL保存一个对应的文件,得到的结果类似

代码

BEGIN{

FS="|"

}

!arr$1,$2++{

arr1$1++

}

END{

for(i in arr1) {

print i, arr1i >(i".txt")

}

}
root@Ubuntu:~# awk -f 1.awk demo3.txt

root@Ubuntu:~# ls -al

总计 92

drwx------ 6 root root 4096 8月 5 09:50 .

drwxr-xr-x 19 root root 4096 8月 3 17:32 ..

-rw-r--r-- 1 root root 109 8月 5 09:50 1.awk
-rw-r--r-- 1 root root 11 8月 5 09:50 a.com.cn.txt

-rw-r--r-- 1 root root 25 8月 4 10:19 awk

-rw------- 1 root root 973 8月 4 17:19 .bash_history

-rw-r--r-- 1 root root 3106 10月 17 2022 .bashrc
-rw-r--r-- 1 root root 11 8月 5 09:50 b.com.cn.txt

drwx------ 2 root root 4096 8月 3 18:13 .cache
-rw-r--r-- 1 root root 11 8月 5 09:50 c.com.cn.txt

drwxr-xr-x 2 root root 4096 8月 4 17:26 .cookiecutters

-rw-r--r-- 1 root root 566 8月 4 16:17 demo1.txt

-rw-r--r-- 1 root root 250 8月 5 09:24 demo2.txt

-rw-r--r-- 1 root root 300 8月 5 09:35 demo3.txt

-rw-r--r-- 1 root root 611 8月 5 09:08 demo.awk

-rw-r--r-- 1 root root 984 8月 5 08:50 dwmo.awk

-rw------- 1 root root 20 8月 4 10:37 .lesshst

-rw-r--r-- 1 root root 161 10月 17 2022 .profile

drwx------ 5 root root 4096 8月 3 17:39 snap

drwx------ 2 root root 4096 8月 3 17:39 .ssh

-rw------- 1 root root 8280 8月 5 09:50 .viminfo

运行结果

root@Ubuntu:~# cat a.com.cn.txt

a.com.cn 2

root@Ubuntu:~# cat b.com.cn.txt

b.com.cn 2

root@Ubuntu:~# cat c.com.cn.txt

c.com.cn 1

3.根据某字段去重

去掉uid=xxx重复的行

案例

2019-01-13_12:00_index?uid=123

2019-01-13_13:00_index?uid=123

2019-01-13_14:00_index?uid=333

2019-01-13_15:00_index?uid=9710

2019-01-14_12:00_index?uid=123

2019-01-14_13:00_index?uid=123

2019-01-15_14:00_index?uid=333

2019-01-16_15:00_index?uid=9710

首先利用uid去重,我们需要利用?进行划分,然后将uid=xxx保存在数组中,这是判断重复的依据

然后统计uid出现次数,第一次出现统计,第二次不统计

运行结果

root@Ubuntu:~# vim demo2.txt

root@Ubuntu:~# awk -F"?" '!arr$2++{print}' demo2.txt

2019-01-13_12:00_index?uid=123

2019-01-13_14:00_index?uid=333

2019-01-13_15:00_index?uid=9710

4.正则表达式

1)认识正则

(1)介绍

  正则表达式应用广泛,在绝大多数的编程语言都可以完美应用,在Linux中,也有着极大的用处。

  使用正则表达式,可以有效的筛选出需要的文本,然后结合相应的支持的工具或语言,完成任务需求。

  在本篇博客中,我们使用grep/egrep来完成对正则表达式的调用

(2)正则表达式类型

正则表达式可以使用正则表达式引擎实现,正则表达式引擎是解释正则表达式模式并使用这些模式匹配文本的基础软件。

在Linux中,常用的正则表达式有:

  • POSIX 基本正则表达式(BRE)引擎

  • POSIX 扩展正则表达式(BRE)引擎

2)匹配字符

  • . 匹配任意单个字符,不能匹配空行

  • \[\] 匹配指定范围内的任意单个字符

  • \^ 取反

  • :alnum:\] 或 \[0-9a-zA-Z

  • :alpha:\] 或 \[a-zA-Z

  • :upper:\] 或 \[A-Z

  • :lower:\] 或 \[a-z

  • :blank: 空白字符(空格和制表符)

  • :space: 水平和垂直的空白字符(比:blank:包含的范围广)

  • :cntrl: 不可打印的控制字符(退格、删除、警铃...)

  • :digit:\] 十进制数字 或\[0-9

  • :xdigit:十六进制数字

  • :graph: 可打印的非空白字符

  • :print: 可打印字符

  • :punct: 标点符号

3)匹配次数

  • * 匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配

  • .* 任意前面长度的任意字符,不包括0次

  • \? 匹配其前面的字符0 或 1次

  • + 匹配其前面的字符至少1次

  • {n} 匹配前面的字符n次

  • {m,n} 匹配前面的字符至少m 次,至多n次

  • {,n} 匹配前面的字符至多n次

  • {n,} 匹配前面的字符至少n次

4)位置锚定:定位出现的位置

  • ^ 行首锚定,用于模式的最左侧

  • $ 行尾锚定,用于模式的最右侧

  • ^PATTERN$,用于模式匹配整行

  • ^$ 空行

  • ^\[:space:].*$ 空白行

  • < 或 \b 词首锚定,用于单词模式的左侧

  • > 或 \b 词尾锚定;用于单词模式的右侧

  • <PATTERN>

5)分组和后向引用

① 分组:() 将一个或多个字符捆绑在一起,当作一个整体进行处理

  分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为: \1, \2, \3, ...

② 后向引用

引用前面的分组括号中的模式所匹配字符,而非模式本身

\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

\2 表示从左侧起第2个左括号以及与之匹配右括号之间的模式所匹配到的字符,以此类推

& 表示前面的分组中所有字

相关推荐
稳联技术老娜6 小时前
DeviceNet主站怎么连接西门子PLC,Profinet网关配置手册(那智机器人)
服务器·网络·数据库
三十..6 小时前
Ceph 三大存储接口深度实践与数据保护指南
运维·ceph
9分钟带帽6 小时前
linux_系统开机自动执行shell脚本
linux·服务器
蝶豆花7 小时前
基于商城系统的功能,自动化,性能-测试报告
运维·自动化
袋鼠云数栈7 小时前
从前端到基础设施,ACOS 如何打通企业全链路可观测
运维·前端·人工智能·数据治理·数据智能
黎阳之光7 小时前
视频孪生智护供水生命线:黎阳之光赋能医疗与园区水务高质量升级
运维·物联网·算法·安全·数字孪生
消失在人海中7 小时前
oracle 数据库多表关联查询
服务器·数据库·oracle
志栋智能8 小时前
AI驱动无代码:降低巡检超自动化的门槛
大数据·运维·网络·人工智能·自动化
嵌入式小能手8 小时前
飞凌嵌入式ElfBoard-进程间的通信之命名管道
linux·服务器·算法
AOwhisky8 小时前
Ceph系列第六期:Ceph 文件系统(CephFS)精讲
linux·运维·网络·笔记·ceph