个人博客,记录知识防止遗忘
awk使用实例: awk+sed 实现段落级文本处理
awk使用实例: awk+sed 实现段落级文本处理

awk使用实例: awk+sed 实现段落级文本处理

内容大纲

1    情景:

在处理彼此有关联的多行数据时, 需要将内容分段落, 随后逐段进行内部操作, 或将每个段落作为整体处理,
此时用sed+awk来实现

例如以下需求:
在一堆杂乱的日志文件中筛选出需要的内容, 要求是必须 同时含有 ”时间线”,”操作人”,”查询内容”


2    处理过程:

2.1 处理步骤详细说明

(1) 使用grep 初步筛选出基础数据

首先将完全不需要的内容取出,只保留上述3个条件相关的内容,此处可以使用grep -E ‘aa|bb|cc’这种方式将所有相关的行全部匹配出来

cat debug2019-09-27.txt |grep -E '^=====.*|manager_name|AS.*FROM mt_.*content LIKE'

执行结果如下,(此处只截图一小部分,部分敏感信息打码)
image.png

(2) 使用sed 将基础数据分段落(插入分隔符)

全部挑出来之后发现有很多都是只含有其中1个或2个信息点的,而最终需求是必须3个点都包含.
这种情况可以采用分段落, 然后每个段落单独检测来实现
而要分段落,就需要段落分隔符,为了方便,需要用sed插入段落分割符

# 使用sed 在每行 "====" 这种时间线之前 ,都插入2个空白行作为段落分隔符
cat debug2019-09-27.txt |grep -E '^=====.*|manager_name|AS.*FROM mt_.*content LIKE' \
 |sed '/^=====.*/i\\n'

执行结果如下所示,每个时间线之前,都有2个空白行
image.png

(3) 使用 awk 检测每一个段落是否符合要求

此时可以使用awk来分段落检测处理了,
awk原本默认每次读入一行,随后逐个字段进行操作.
此处转换思维,令awk每次读入一个段落,随后逐行进行操作.

所以FS指定分隔符为换行符,RS指定分隔符为sed加进去的2个空白行
接着匹配出同时含有时间线、操作人、like查询内容的所有段落, 然后用print $0输出该段落的所有字段(所有行)

 cat debug2019-09-27.txt |grep -E '^=====.*|manager_name|AS.*FROM mt_.*content LIKE' \
 |sed '/^=====.*/i\\n'|awk -v FS="\n" -v RS="\n\n" '/.*====.*manager_name.*LIKE.*/{ print $0}'

最后结果如下,最终实现了需求:剔除无用信息,保证每个段落中都有必要的3个信息点
image.png

(4) 解决shell邮件发送问题,

至此,已实现了需求,但是若结合脚本,或者利用shell发送邮件,则会遇到错误,
因为\r会导致linux变量存入失败,也会导致邮件发送时,正文变为附件xxx.bin的情况
此时需要使用tr-d将 \r去除

2.2 整个过程的完整命令:

cat debug2019-09-27.txt |grep -E '^=====.*|manager_name|AS.*FROM mt_.*content LIKE'
 |sed '/^=====.*/i\\n'|awk -v FS="\n" -v RS="\n\n" '/.*====.*manager_name.*LIKE.*/{ print $0}'|tr -d "\r"

3    拓展: 搭配脚本自动检测

编写简易脚本,搭配crontab 每5分钟检测一次, 当有新数据存在时立即邮件告警
脚本如下所示, 敏感信息已替换

 #!/bin/bash

export LANG=en_US.UTF-8

#当天所有的查询记录(时间,操作人,like内容)
content=$(cat debug$(date +%F).txt |grep -E '^=====.*|manager_name|AS.*FROM mt_.*content LIKE' \
 |sed '/^=====.*/i\\n'|awk -v FS="\n" -v RS="\n\n" '/.*====.*manager_name.*LIKE.*/{ print $0}'|tr -d "\r" )

#查询记录的总行数
content_total=echo "${content}" |wc -l 

#每一次脚本执行完后,会将最新的 content_total 的值录入临时文件,方便下次脚本执行时进行比对
#从临时文件取出上次的行数,并将其传递给 ${content_total_ago} ,若a为空,则赋予默认值0
a=cat linshi.txt 
content_total_ago=${a:-"0"}

if [[ ${content_total} -gt ${content_total_ago} ]] ;then

  #上次脚本执行过后,又新增的content 行数
  content_total_newadd=expr ${content_total} - ${content_total_ago}
  #新增的content内容
  content_newadd= echo "${content}" |tail -n ${content_total_newadd} 

  #当天总共有多少次like查询(不算时间和操作人等信息)
  like_total= echo "${content}" |grep 'LIKE' |wc -l 

#发送告警邮件
  echo "
  今日like模糊查询总次数为:${like_total}
  新查询的操作时间、操作人、内容如下

${content_newadd}

使用以下命令可查看今天所有的查询记录
cat debug$(date +%F).txt |egrep '^=====.*|manager_name|AS.*FROM mt_.*content LIKE'  |sed '/^=====.*/i\\\n'|awk -v FS=\"\\n\" -v RS=\"\\n\\n\" '/.*====.*manager_name.*LIKE.*/{ print \$0}'
" |mail -s like_logs "123456@qq.com"

fi

echo " ${content_total}" > linshi.txt

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注