美文网首页
shell 字符串处理和数值排序

shell 字符串处理和数值排序

作者: 云中有诗 | 来源:发表于2019-07-31 17:57 被阅读0次

    最近一个哥们的需求是对日志里面的数据做一下监控,要求是日志里面的某个字段的值,并求这一值得最大最小值。

    日志样例:

    10:46:13.840 [Thread-11] WARN  c.c.b.s.s.c.Status - TPS=137504, delay=7,40023ms, avgTPS=137536, avgDelay=7,400194ms, objs=137536, totalTime=1s
    10:46:14.840 [Thread-10] WARN  c.c.b.s.s.c.Status - TPS=138896, delay=7,31168ms, avgTPS=138304, avgDelay=7,355904ms, objs=276640, totalTime=2s
    10:46:15.840 [Thread-12] WARN  c.c.b.s.s.c.Status - TPS=139904, delay=7,26450ms, avgTPS=138864, avgDelay=7,326106ms, objs=416592, totalTime=3s
    10:46:16.840 [Thread-12] WARN  c.c.b.s.s.c.Status - TPS=143504, delay=7,08871ms, avgTPS=140044, avgDelay=7,265344ms, objs=560176, totalTime=4s
    10:46:17.840 [Thread-12] WARN  c.c.b.s.s.c.Status - TPS=143776, delay=7,07661ms, avgTPS=140790, avgDelay=7,226796ms, objs=703952, totalTime=5s
    10:46:18.840 [Thread-12] WARN  c.c.b.s.s.c.Status - TPS=143376, delay=7,09954ms, avgTPS=141224, avgDelay=7,205253ms, objs=847344, totalTime=6s
    

    需要获得得是avgDelay这一列的数值
    首先需要做字符串匹配

    line=`echo ${line#*=}`
    line=`echo ${line%m*}`
    line=`echo ${line/,/.}`
    

    上面的含义是:

    1. echo ${line#*=} # 号是运算符 *= 表示从左边开始删除第一个 = 号及左边的所有字符
    2. echo ${line%m} %号是运算符 m 表示从右边开始,删除第一个 m 号及右边的字符
    3. echo ${line/,/.} /表示单词匹配,号 用.号代替

    其他的相关符号使用可见下

    >假设有变量 var=http://www.aaa.com/123.htm.
    >
    >1. # 号截取,删除左边字符,保留右边字符。
    >
    >echo ${var#*//}
    > 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符
    >即删除 http://
    >结果是 :www.aaa.com/123.htm
    >
    >2. ## 号截取,删除左边字符,保留右边字符。
    >
    >echo ${var##*/}
    > 
    >
    >##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符
    >即删除 http://www.aaa.com/
    >
    >结果是 123.htm
    >
    >3. %号截取,删除右边字符,保留左边字符
    >
    >echo ${var%/*}
    > 
    >
    >%/* 表示从右边开始,删除第一个 / 号及右边的字符
    >
    >结果是:http://www.aaa.com
    >
    >4. %% 号截取,删除右边字符,保留左边字符
    >
    >echo ${var%%/*}
    > %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符
    >结果是:http:
    >
    >5. 从左边第几个字符开始,及字符的个数
    >
    >echo ${var:0:5}
    > 
    >
    >其中的 0 表示左边第一个字符开始,5 表示字符的总个数。
    >结果是:http:
    >
    >6. 从左边第几个字符开始,一直到结束。
    >
    >echo ${var:7}
    > 
    >
    >其中的 7 表示左边第8个字符开始,一直到结束。
    >结果是 :www.aaa.com/123.htm
    >
    >7. 从右边第几个字符开始,及字符的个数
    >
    >echo ${var:0-7:3}
    > 
    >
    >其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。
    >结果是:123
    >
    >8. 从右边第几个字符开始,一直到结束。
    >
    >echo ${var:0-7}
    > 
    >
    >表示从右边第七个字符开始,一直到结束。
    >结果是:123.htm
    >
    >注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)
    
    > 一个替换的例子:
    str="apple, tree, apple tree"  
    echo ${str/apple/APPLE}   # 替换第一次出现的apple  
    echo ${str//apple/APPLE}  # 替换所有apple  
    echo ${str/#apple/APPLE}  # 如果字符串str以apple开头,则用APPLE替换它  
    echo ${str/%apple/APPLE}  # 如果字符串str以apple结尾,则用APPLE替换它  
    

    故读取文件并匹配替换的代码如下:

    #获取文件名
    logpath=$1
    
    echo "raw data:"
    for line in `cat $logpath`
    do
    #匹配avgDelay字符串
    if [[ ${line} == *"avgDelay"* ]];then
    #截取数字并处理
    line=`echo ${line#*=}`
    line=`echo ${line%m*}`
    line=`echo ${line/,/.}`
    echo $line >> logmidfile.txt
    fi
    done
    

    对于排序 Linux许多发行版提供sort命令以行为单位对文本进行排序

    一个以数字进行排序的例子:sort -n sort.txt
    # sort.txt

    1 mac 2000
    3 winxp 4000
    2 linux 1000
    4 win7 1000
    2 linux 1000

    结果:
    1 mac 2000
    2 linux 1000
    2 linux 1000
    3 winxp 4000
    4 win7 1000

    故全部实现代码如下:

    #!/bin/bash
    ###################################################################
    #*名称     --%@NAME:日志收集排序
    #*功能描述 --%@COMMENT: 
    #*执行周期 --%@PERIOD:
    #*参数     --%@PARAM:v_hour 帐期 YYYYMMDDHH
    #*参数     --%@PARAM:logpath 日志路径
    #*创建人   --%@CREATOR:
    #*创建时间 --%@CREATED_TIME:2019-07-31
    #*层次     --%@LEVEL:
    #*备注     --%@REMARK:
    #*修改记录 --%@MODIFY:
    ####################################################################
    #参数要求,一共需要1个参数
    if [ "$#" -ne "1" ]; then
            echo "必须是1个参数logpath"
            exit 1
    fi
    
    #获取文件名
    logpath=$1
    #删除中间文件
    rm -rf logmidfile.txt
    
    echo "raw data:"
    for line in `cat $logpath`
    do
    #匹配avgDelay字符串
    if [[ ${line} == *"avgDelay"* ]];then
    #截取数字并处理
    line=`echo ${line#*=}`
    line=`echo ${line%m*}`
    line=`echo ${line/,/.}`
    echo $line >> logmidfile.txt
    fi
    done
    
    #创建数组
    array=(0)
    #创建计数标识
    le=0 
    #排序文件
    sort logmidfile.txt -n
    echo "sort is done:"
    for line2 in `cat logmidfile.txt`
    do
    echo $line2
    array[le]=$line2
    le=`expr $le + 1` #标识++
    done
    
    echo "max:${array[0]}  min:${array[(($le-1))]}"
    
    
    #删除中间文件
    rm -rf logmidfile.txt
    

    参考资料:
    https://www.cnblogs.com/delav/p/9956819.html
    https://www.cnblogs.com/gaochsh/p/6901809.html
    https://www.linuxidc.com/Linux/2019-05/158678.htm
    https://www.cnblogs.com/zwgblog/p/6031256.html
    https://www.cnblogs.com/gaochsh/p/6901809.html

    相关文章

      网友评论

          本文标题:shell 字符串处理和数值排序

          本文链接:https://www.haomeiwen.com/subject/nogtdctx.html