PERL REGEX:单个字符串中的多个排除/模式

时间:2015-02-01 20:14:37

标签: regex string perl

对于一些黑暗而神秘的事情,我的注册表并没有拉出我期待的东西;

示例:

要清理的示例文字:

[PROTOCOL (Id:"hashguy82", ProcessID: 45)] 
[APP (Id:"hashguy83", ProcessID: 67)]

我只需要用户名

我的代码是:

\[(PROTOCOL|APP)\s\(Id:\"(\w+)\"\, \s ProcessID\: \s \d+\)] \s

(PROTOCOL|APP)我的意思是定义不同的可能模式

\s我的意思是空格

输出:没有错误只是空白输出,因为我从根本上认为格式是正确的,但我无法理解我错过了什么。

示例字符串:

2015-01-27 00:00:09,654 TRACE  [APP (Id:"HashMap81", ProcessId: 62)] PerformanceLogger (PerformanceLogger.Python:29) - Client:344,UserId:13383,Ip:127.0.0.1,DurationMillis:272,DurationText:0.272 seconds,Path:MyClass.myMethod

完整代码:

my $file = 'path_my_file.txt';
open my $fh, "<", $file or die "Could not open $file: $!";


while (<$fh>) {
    my @fields = m{^
        (\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:[\d,]+)
        \s (WARNING|TRACE) \s\s
        qr/ \[ (?: APP| PROTOCOL) \s* \(Id:"(\w+)", \s* ProcessID: \s* \d+ \) \] /x \s
        \s PerformanceLogger \s \(PerformanceLogger\.Python\:\d+\) \s - \s
        Client:(\d+),
        UserId:(\d+),
        Ip:([\d.]+),
        DurationMillis:\d+,
        DurationText:([\d.]+) \s seconds,
        Path:/(\S+)
    $}x
    or next;

    printf('$date=%s; $level=%s; $user=%s; $client_id=%s; $user_id=%s; $ip=%s; $elapsedTime=%s; $classMethod=%s', @fields);
    print "\n";

2 个答案:

答案 0 :(得分:1)

除非使用/x修饰符,否则必须在目标字符串中匹配正则表达式中的空格和制表符。在你的模式

\[(PROTOCOL|APP)\s\(Id:\"(\w+)\"\, \s ProcessID\: \s \d+\)] \s

你需要一个空格后跟逗号后面的空白字符。 (\s字符类匹配ASCII控制字符HTLFVTFFCR以及空格字符。 )同样,在第二个冒号之后,你需要一个空格,后面跟一个空格字符,然后是另一个空格,让模式匹配。在这两种情况下,目标字符串中只有一个空格,因此模式不匹配。在最后的方括号之后,你还要求一个空格后跟一个空白字符,但你的数据似乎在括号结束。您是否尝试匹配终止换行符?

这样可行

\[(PROTOCOL|APP)\s\(Id:\"(\w+)\"\,\sProcessID\:\s\d+\)]

但双引号",逗号,和冒号:不需要转义,最好在/x修饰符上使用(?: ... )修饰符琐碎的模式,这样你就可以添加无关紧要的空白来揭示它们的结构。如果您不需要捕获该部分字符串,最好在PROTOCOLAPP周围使用非捕获括号use strict; use warnings; my $re = qr/ \[ (?: PROTOCOL | APP ) \s* \(Id:"(\w+)", \s* ProcessID: \s* \d+ \) \] /x; while (<DATA>) { print $1, "\n" if /$re/; } __DATA__ [PROTOCOL (Id:"hashguy82", ProcessID: 45)] [APP (Id:"hashguy83", ProcessID: 67)]

看一下这个程序,看起来就像你问的那样。

hashguy82
hashguy83

<强>输出

{{1}}

答案 1 :(得分:0)

解决方案可能并不优雅,但却符合我的目的:

while (<$fh>) {
    my @fields = m{^
        (\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:[\d,]+)
        \s (?: WARNING | TRACE) \s\s
        \[(?: APP | PROTOCOL)\s[(]Id:["](\w+)",\sProcessID:\s\d+\)]
        \s PerformanceLogger \s \(PerformanceLogger\.Python\:\d+\) \s - \s
        Client:(\d+),
        UserId:(\d+),
        Ip:([\d.]+),
        DurationMillis:\d+,
        DurationText:([\d.]+) \s seconds,
        Path:(\S+)
    $}x
    or next;

如果我使用补丁解决方案,请告诉我....