使用python正则表达式解析文本文件中的相关线组

时间:2018-01-31 23:26:46

标签: python regex

我有这个文件包含这个文字:

$ more audit.log
2018-01-31 15:34:08 GMT:10.34.160.60(63788):agent3@pem:[31884]00000:LOG:  statement: DROP TABLE tmp_zombies
2018-01-31 15:58:52 GMT:127.0.0.1(45050):agent1@pem:[13182]00000:LOG:  statement: CREATE TEMP TABLE tmp_zombies(jagpid int4)
2018-01-31 15:58:52 GMT:127.0.0.1(45050):agent1@pem:[13182]00000:LOG:  statement: DROP TABLE tmp_zombies
2018-01-31 16:24:00 GMT:10.34.160.55(57199):agent8@pem:[27888]00000:LOG:  statement: CREATE TEMP TABLE tmp_zombies(jagpid int4)
2018-01-31 16:24:00 GMT:10.34.160.55(57199):agent8@pem:[27888]00000:LOG:  statement: DROP TABLE tmp_zombies
2018-01-31 21:08:47 GMT:[local]:pgsql@p106:[26349]00000:LOG:  statement: create table global_pg_audit
        (
           rolename         text not null,
           stmt_timestamp   timestamp not null,
           source_ip        text,
           target_ip        text,
           dbname           text,
           pid              text,
           statement_type   text,
           statement        text
        );
2018-01-31 15:34:08 GMT:10.34.160.60(63788):agent3@pem:[31884]00000:LOG:  statement: DROP TABLE tmp_zombies

当我运行这个python代码时:

    import re
    fullpathname='./audit.log'
    regex_pattern=re.compile(r'^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(.*?)$',re.MULTILINE|re.DOTALL)
    with open(fullpathname,'r') as f:
        log_entries = regex_pattern.findall(f.read())
    counter=0
    for entry in log_entries:
        print '%d=>['%(counter),entry,']'
        counter=counter+1

输出如下:

0=>[ ('2018-01-31 15:34:08', ' GMT:10.34.160.60(63788):agent3@pem:[31884]00000:LOG:  statement: DROP TABLE tmp_zombies') ]
1=>[ ('2018-01-31 15:58:52', ' GMT:127.0.0.1(45050):agent1@pem:[13182]00000:LOG:  statement: CREATE TEMP TABLE tmp_zombies(jagpid int4)') ]
2=>[ ('2018-01-31 15:58:52', ' GMT:127.0.0.1(45050):agent1@pem:[13182]00000:LOG:  statement: DROP TABLE tmp_zombies') ]
3=>[ ('2018-01-31 16:24:00', ' GMT:10.34.160.55(57199):agent8@pem:[27888]00000:LOG:  statement: CREATE TEMP TABLE tmp_zombies(jagpid int4)') ]
4=>[ ('2018-01-31 16:24:00', ' GMT:10.34.160.55(57199):agent8@pem:[27888]00000:LOG:  statement: DROP TABLE tmp_zombies') ]
5=>[ ('2018-01-31 21:08:47', ' GMT:[local]:pgsql@p106:[26349]00000:LOG:  statement: create table global_pg_audit ') ]
6=>[ ('2018-01-31 15:34:08', ' GMT:10.34.160.60(63788):agent3@pem:[31884]00000:LOG:  statement: DROP TABLE tmp_zombies') ]
7=>[ ('2018-01-31 15:58:52', ' GMT:127.0.0.1(45050):agent1@pem:[13182]00000:LOG:  statement: CREATE TEMP TABLE tmp_zombies(jagpid int4)') ]

注意输出中的第5行,代码中没有包含整个语句,应该是:

    create table global_pg_audit
        (
           rolename         text not null,
           stmt_timestamp   timestamp not null,
           source_ip        text,
           target_ip        text,
           dbname           text,
           pid              text,
           statement_type   text,
           statement        text
        );

代码有什么问题?

非常感谢!

1 个答案:

答案 0 :(得分:1)

你的正则表达式固定在行尾:

^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(.*?)$

由于您已启用多线模式,$会在换行符时匹配。这就是为什么匹配在global_pg_audit之后结束。

您希望匹配直到以日期开头的下一行。你可以使用前瞻来做到这一点:

^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})(.*?)(?=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}|\Z)

替换|\Z允许正则表达式匹配最后一行,即使它后面没有日期。

另请参阅regex demo