使用sed / awk和regex处理日志

时间:2011-08-10 05:33:07

标签: regex sed awk logging

我有一个非常详细的PHP脚本生成的1000个日志文件。一般结构如下

###Unknown no of lines, which I want to ignore###
=================================================
$insert_vars['cdr_pkey']=17568
$id<TAB>$g1<TAB>$i1<tab>rating1<TAB>$g2<TAB>$i2<tab>rating2 #<TAB>more $gX,$iX,$ratingX
#numerical values of $id $g1 $i1 etc. separated by tab
#numerical values of ---""---
#I do not know how many lines will be there (unique column is $id)
=================================================
###Unknown no of lines, which I want to ignore###

我必须处理这些日志文件并创建一个excel表(我正在考虑csv格式)并报告数据。我真的很擅长excel,但我想输出类似的东西:

cdr_pkey<TAB>id<TAB>g1<TAB>i1<TAB>rating1<TAB>g2<TAB>rating2 #and so on
17568<TAB>1349<TAB>0.0004532<TAB>0.01320<TAB>2.014E-4<TAB>...#rest of numerical values
17568<TAB>1364<TAB>...#values for id=1364
17568<TAB>1321<TAB>...#values for id=1321
...
17569<TAB>1048<TAB>...#values for id=1048
17569<TAB>1426<TAB>...#values for id=1426
...
...

所以我的cdr_pkey是表单中的唯一列,对于每个$cdr_pkey,我有多个$id s,每个$g1,$i1,$rating1...都有自己的一组{{1}}
在测试这种格式后,excel可以读取。现在我只想将它扩展到所有这1000个文件 我只是不确定如何继续前进。下一步是什么?

2 个答案:

答案 0 :(得分:3)

以下bash脚本可以执行与您想要的内容相关的操作。当你说<TAB>时,你的意思是参数化的。我假设您的意思是ascii制表符,但如果您的日志非常冗长以至于拼出<TAB>,则需要相应地修改变量$WHAT_DID_YOU_MEAN_BY_TAB。请注意,这个脚本很少有做The Right Thing™;它将整个文件读入一个字符串变量,根据日志文件的大小,甚至可能无法实现。从好的方面来说,如果您认为更好的话,可以轻松修改脚本以进行两次传递。

#!/bin/bash

WHAT_DID_YOU_MEAN_BY_TAB='\t'

if [[ $# -ne 1 ]] ; then echo "Requires one argument: the file to process" ; exit 1 ; fi

FILENAME="$1"

RELEVANT=$(sed -n '/^==*$/,/^==*$/p' "$FILENAME" | sed '1d' | head -n '-1')
CDR_PKEY=$(echo "$RELEVANT" | \
    grep '$insert_vars\['"'cdr_pkey'\]" | \
    sed 's/.*=\(.*\)/\1/')
echo "$RELEVANT" | sed '1,2d' | \
    sed "s/.*/${CDR_PKEY}$WHAT_DID_YOU_MEAN_BY_TAB\0/"

以下find命令是一个示例用法,但您的情况将取决于您的日志的组织方式。

find . LOG_PATTERN -exec THIS_SCRIPT '{}' \;

最后,我忽略了将CSV标头放在输出上的问题。这很容易在带外完成。

(编辑:更新了脚本以反映评论中的讨论。)

答案 1 :(得分:1)

编辑:詹姆斯告诉我,将sed中的echo... 1d ...更改为... 1,2 ...并删除grep -v 'id'应该可以解决问题。
确认它有效。所以在下面改变它。再次感谢James Wilcox

<小时/> 基于@James脚本,这就是我想出来的。我只是将最后的回音传送到grep -v 'id'
再次感谢James Wilcox

WHAT_DID_YOU_MEAN_BY_TAB='\t'

if [[ $# -lt 1 ]] ; then echo "Requires at least one argument: the files to process" ; exit 1 ; fi

echo -e "key\tid\tg1\ti1\td1\tc1\tr1\tg2\ti2\td2\tc2\tr2\tg3\ti3\td3\tc3\tr3"

for i in "$@"
do
    FILENAME="$i"
    RELEVANT=$(sed -n '/^==*$/,/^==*$/p' "$FILENAME" | sed '1d' | head -n '-1')
    CDR_PKEY=$(echo "$RELEVANT" | \
        grep '$insert_vars\['"'cdr_pkey'\]" | \
        sed 's/.*=\(.*\)/\1/')
    echo "$RELEVANT" | sed '1, 2d' | \
        sed "s/.*/${CDR_PKEY}$WHAT_DID_YOU_MEAN_BY_TAB\0/"
    #the one with grep looked like :-
    #echo "$RELEVANT" | sed '1d' | \
        #sed "s/.*/${CDR_PKEY}$WHAT_DID_YOU_MEAN_BY_TAB\0/" | grep -v 'id'
done