shell查找log文本中的异常时间间隔字符串(awk、正则表达式、awk调用shell和自定义函数)

目录

前言

旧文贴上来,只是为了增加显示一个shell分类。

概述:
一般log文件处理,会遇到匹配字符串、对字符串某一部分截取、做计算处理等问题,这篇文章以一个应用实例,来:

  • 熟悉一下Shell的语法、语义、顺序
  • 自定义函数、awk文本处理语言
  • 正则表达式

代码目标:
匹配log文本中的指定字符串,如“111111111111111111111111”,然后比对相邻的匹配字符串的行开头的时间戳,若时间间隔超出阈值,则打印当前行。

|21:07:45:487| -  actual sleep time=16572(ms)
|21:07:45:512| - 
|21:07:45:512| - 111111111111111111111111111111111111111111111111111111111111111
|21:07:45:527| - 
|21:07:45:527| - 
|21:07:47:245| - 
|21:07:47:245| -  actual sleep time=1746(ms)
|21:07:47:324| - 
|21:07:47:324| - 
|21:07:50:712| - 
|21:07:50:712| -  actual sleep time=3453(ms)
|21:07:50:712| - 
|21:07:50:715| - 222222222222222222222222222222222222222222222222222222222222222
|21:07:50:780| - 
|21:07:50:780| - 
|21:07:58:712| - 
|21:07:58:713| -  actual sleep time=8108(ms)
|21:07:58:744| - 
|21:07:58:744| - 
|21:08:03:529| - 
|21:08:03:529| -  actual sleep time=4882(ms)
|21:08:03:529| - 
|21:08:03:532| - 111111111111111111111111111111111111111111111111111111111111111
|21:08:03:532| - 
|21:08:03:532| - 
|21:08:04:842| - 
|21:08:04:843| -  actual sleep time=1171(ms)

环境

Ubuntu 16.04.2, GNU bash, version 4.3.48(1)-release-(x86_64-pc-linux-gnu)
MINGW32, GNU bash, version 3.1.23<1>-release <i686-pc-msys>

SHELL

关于shell、python

shell 应该属于宏语言,顾名思义是系统的壳,方便与系统交互的在以下情况下,不使用shell,因为shell对此无能为力;如:跨平台,较复杂数学操作(如浮点运算,精确运算等),图形化界面 GUI,I/O 或socket 接口,多维数组,对效率要求很高等。

  1. shell:简单,开发迅速,专注系统(比如:Linux)管理领域。
  2. python:通用脚本语言,功能强大,跨平台(比如:Windows和Linux),严谨;
  3. Python可以调用图形库,可以直接做网络应用,甚至直接嵌入其它语言,跨平台;
  4. shell就是和系统结合得比较紧密,其内部数据处理方面,侧重文本(或者说字符串,或字符流)处理,而对运算和其他基本数据结构的原生较弱。

如果使用python去写脚本来处理日常事务的话,相对于shell是一件比较麻烦的事情,因为我可以使用shell在花费更少的时间内,比较熟练地使用awk、sed和grep这些常用的命令在非常简短的脚本语句内,完成python一大段代码所能够完成的功能。

当然,上述讲述,仅针对python和shell做过一些底层驱动和字符文本处理,在其他应用场合两者的对比,不在本文讨论范围内。

进制规则

Linux Shell 进制错误 - value too great for base

Shell 编程进行数学运算时,如果有字符 ‘0’ 打头的数 Bash 会当做八进制解释。解决办法是在变量或数字前加前缀“10#”,例如附录代码的compare_time()的处理

特殊符号

Linux Shell中的特殊符号和含义简明总结(包含了绝大部份)
https://www.jb51.net/article/51342.htm

数学计算

NULL

shell函数

NULL

正则表达式

简介

正则表达式是包含在 两个斜杠之间 的一个或多个字符,在后一个斜杠的后面,可以指定一个或多个选项。
var regExp = /pattern/flags
其中,“pattern”为指定的匹配模式,flags为 0个 或多个可选项,这些选项及其含义如下:
• i:表示忽略大小写,就是在字符串匹配的时候不区分大小写。
• g:表示全局匹配,即匹配字符串中出现的所有模式。
• m:表示进行多行匹配。
题目中的合法表达式。
再举一些合法表达式的例子

var regExp1 = /abc/;                              
var regExp2 = /abc/gi;                              
var regExp3 = /^JavaScript/;                              
var regExp4 = /0[0-9][0-9]*/;                              
var regExp5 = /\binter/i;  
常用规则

这里写图片描述

可视化正则表达式

http://www.regexper.com

awk

Awk同shell一样,是一门脚本语言,有自己的语法和词汇

Awk内部调用内部shell函数
在awk中可以直接执行shell命令
zoer@ubuntu:~$ touch a  
zoer@ubuntu:~$ touch b  
zoer@ubuntu:~$ cat a.txt   
a  
b  
zoer@ubuntu:~$ awk '{cmd="rm "$0;system(cmd)}' a.txt   
zoer@ubuntu:~$ ls  
a.txt      dd            important    mysql                py       testdata  
daemon.py  Desktop       installer    mysql_install_db.sh  stu  
data       dfadsfadfadf  jdk1.6.0_33  Public               stu.txt  
zoer@ubuntu:~$   

我们在awk中组装命令并且最后使用system()来执行。每次读入一个文件名并删除这个文件。


下面我们使用awk中执行命令来创建一些文件。

1.  zoer@ubuntu:~$ awk 'BEGIN{count=10;i=0;while(i<count){cmd="touch "i".txt";i++;system(cmd)}}'  
2.  zoer@ubuntu:~$ ls  
3.  0.txt  4.txt  8.txt      dd         jdk1.6.0_33          py  
4.  1.txt  5.txt  9.txt      Desktop    mysql                stu  
5.  2.txt  6.txt  daemon.py  important  mysql_install_db.sh  stu.txt  
6.  3.txt  7.txt  data       installer  Public               testdata  
getline

先把文件列表存在filename文件中

awk '{system("rm $0")}' filename -------WRONG

因为对于 system来说 $0 不再是某行全部的内容,而是 “sh” , 上面的命令相当于执行“ sh rm sh”
然后

awk '{cmd="rm "$0;system(cmd)}' filename ----OK

下面的也ok

awk '{cmd="rm "$0;cmd|getline }' filename  ---- OK

man awk里面关于getline的说明,大意是说 运行command,同时会把输出存在$0 里面,或参数var中。

       command | getline [var]
                             Run command piping the output either into $0 or var, as above.

       command |& getline [var]
                             Run command as a co-process piping the output either into $0  or  var,  as  above.
                             Co-processes are a gawk extension.
Awk调用自定义带参数shell函数
  • 单参数
function add1()
{
    result=`expr $1 + 1`
    echo $result
}

export -f add1
awk 'BEGIN{p=3;"add1 "p|getline result;print result }'
  • 双参数
function add1()
{
    result=`expr $1 + $2 + 1`
    echo $result
}
export -f add1
awk 'BEGIN{p=3;q=4;"add1 "p" "q|getline result;print result }'
  • system调用
    awk里的system只是获取函数或命令的退出状态值,范围0-255,如果return不在此范围会有问题
function add1()
{
    result=`expr $1 + 1`
    exit $result
}
export -f add1
awk 'BEGIN{p=3;result=system("add1 "p);print result}'
  • shell函数的命令单独赋值给一个变量

这里写图片描述

代码

#!/bin/bash

if [ $# -ne 2 ];
then
    echo "Usage: $0 filename match_str";
    exit -1
fi

filename=$1
match_str=$1

bash_version() {
    local cmd="bash"
    if command -v "$cmd" 2>&1 >/dev/null; then
        ver=$("$cmd" --version | head -n 1)
    else
        ver="missing"
    fi

    printf "%s" "$ver"
}

function compare_time()
{
    # printf "%s\n" $1
    # printf "%s\n" $2

    #分割操作不能直接使用参数全局变量,所以定义临时变量赋值
    local aa=$1
    local bb=$2

    local hour1=${aa:0:2}
    local minute1=${aa:3:2}
    local second1=${aa:6:2}

    local hour2=${bb:0:2}
    local minute2=${bb:3:2}
    local second2=${bb:6:2}

    local dif=$[ $[ 10#$hour2*3600 + 10#$minute2*60 + 10#$second2 ] - $[ 10#$hour1*3600 + 10#$minute1*60 + 10#$second1 ] ]

    if [ $dif -ge 7 ]; then
        echo 1
        return 1
    else
        echo 0
        return 0
    fi
}

printf "%s\n" "----------------------------"

printf "%20s: %s\n" "bash" "$(bash_version)"

#使用shell函数版
export -f compare_time
awk 'BEGIN{ print "Start"; last_time = 0; now_time = 0;}
    {
        if(match($0, /(APP_Test1Timer EXPIRED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)/))
        {
            now_time = substr($0, 2, 8)

            # print last_time
            # print now_time

            # awk里的system只是获取函数或命令的退出状态值,范围0-255,如果return不在此范围会有问题
            # ddd=system("compare_time "last_time" "now_time)

            # 获取函数的echo返回值,只能使用getline方式
            "compare_time "last_time" "now_time|getline ddd

            if(ddd > 0)
            {
                print;
            }
            else
            {

            }

            last_time = now_time;
        }
        else
        {

        }
    }
    END{ print "End" }' \
    $filename

#仅使用awk程序版
awk 'BEGIN{ print "Start"; last_time = 0; now_time = 0;}
    {
        if(match($0, /(APP_Test1Timer EXPIRED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)/))
        # if(match($0, /(111111111111111111111111111111111111111111111111111111111111111)/))
        # if(match($0, /(222222222222222222222222222222222222222222222222222222222222222)/))

        {
            hour = substr($0, 2, 2)
            minute = substr($0, 5, 2)
            second = substr($0, 8, 2)

            now_time = hour*3600 + minute * 60 + second

            # print last_time
            # print now_time

            if((now_time - last_time) > 6)
            {
                print;
            }
            else
            {

            }

            last_time = now_time;
        }
        else
        {

        }
    }
    END{ print "End" }' \
    $filename

printf "%s\n" "----------------------------"

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值