Perl使用正则表达式捕获带有日志的组

时间:2019-02-26 07:21:30

标签: regex perl

我正在尝试转换此日志行:

9:[2019-02-25 00:39:01] production.DEBUG: JOB-VARS : {"phone_numbers":["+9660599291111"],"message":"Your verification code is: 74222","twilio":{},"objectKey":"job:class:App\\Jobs\\SmsJob:000000001328e347000000003113b4f8","connection":"sqs-high","queue":null,"delay":null,"job":{},"JOB-CLASS":"App\\Jobs\\SmsJob"} [] []
16:[2019-02-25 00:50:06] production.DEBUG: JOB-VARS : {"phone_numbers":["+9660533001112"],"message":"Your verification code is: 31231","twilio":{},"objectKey":"job:class:App\\Jobs\\SmsJob:00000000206561fd000000003fb01b05","connection":"sqs-high","queue":null,"delay":null,"job":{},"JOB-CLASS":"App\\Jobs\\SmsJob"} [] []
54:[2019-02-25 03:59:42] production.DEBUG: JOB-VARS : {"phone_numbers":["+9647707771113"],"message":"Your verification code is: 64628","twilio":{},"objectKey":"job:class:App\\Jobs\\SmsJob:0000000003baa9660000000022c0679c","connection":"sqs-high","queue":null,"delay":null,"job":{},"JOB-CLASS":"App\\Jobs\\SmsJob"} [] []

插入如下所示的电子表格:

|       time          |   phone number   |            sms job id          | 
---------------------------------------------------------------------------
| 2019-02-25 00:39:01 | +96605992911111  |000000001328e347000000003113b4f8|
| 2019-02-25 00:50:06 | +96605992911112  |00000000206561fd000000003fb01b05|
| 2019-02-25 03:59:42 | +96605992911113  |0000000003baa9660000000022c0679c|

我试图写这行

perl -ne 'print "$1,$2\n" if /\[(.*?)\].+(\[.*\])/' filename

但是我得到的只是这个:

2019-02-25 00:39:01,[]
2019-02-25 00:50:06,[]
2019-02-25 03:59:42,[]

我被困在捕获第二组。想法?

4 个答案:

答案 0 :(得分:1)

您可以尝试此模式\[([^\]]++)\].+phone\_numbers\D++(\d++).+SmsJob\:(\w++)

说明:

\[([^\]]++)\]将匹配方括号内的日期,并成组捕获日期,

.+phone\_numbers\D++(\d++)将匹配任何一个或多个字符,然后依次匹配phone_number,然后匹配一个或多个非数字,然后它将使用(\d++) <捕获组内的实际电话号码。 / p>

.+SmsJob\:(\w++)将首先匹配任何一个或多个字符,然后依次匹配SmsmJob,然后再匹配:,然后再在另一个捕获组中捕获作业ID。

答案 1 :(得分:1)

完全依靠格式的细节,包括所有"[]

perl -wnE'
    say "$1, $2, $3"  
        if /:\[(.*?)\].*?"phone_numbers":\["(.*?)"\].*?SmsJob:(.*?)"/
' file

我使用显式短语(例如"phone_numbers":)来锚定所需的模式。

请注意到处都有非贪婪模式。由于我们为需要捕获的内容提供了方便的文本“锚”,因此没有理由让贪婪的模式陷入混乱。他们很难从心理上进行追踪,可能很难正确地做,而且通常效率较低。

请注意,我在"之后使用SmsJob,因为SmsJob:objectKey中排在最后,因此恰好紧随其后的是",这很方便划定要匹配的模式。但是,如果不确定"是否存在,则需要更改.*?;也许是[0-9a-zA-Z]SmsJob值允许的最小模式),然后是一个以其结尾的文字字符(例如,:等)。

这将从给定样本中正确捕获时间戳,电话号码和SmsJob。


问题中诚实尝试的第二种模式无法捕获期望的内容,因为贪婪的.+一直抓住一切字符串中的最后一对[],因为\[.*\]之后的.+与最后[]匹配,因此整个模式都匹配。

答案 2 :(得分:1)

您当前的正则表达式是如此贪婪,并且给定的输入字符串肯定不同。您也没有尝试获得三个捕获组。尝试以下方法:

\[([\d: -]+)\][^][]+\["([^][]+)"\].*?SmsJob:(\w+)

Perl:

perl -ne 'print "$1,$2,$3\n" if /\[([\d: -]+)\][^][]+\["([^][]+)"\].*?SmsJob:(\w+)/' filename

正则表达式细目:

  • \[从字面上匹配[
  • (第一个捕获组的开始
    • [\d: -]+匹配指定字符(数字,:,空格和-)的组合
  • )捕获组结束
  • \]从字面上匹配]
  • [^][]+匹配[]
  • 之外的任何内容
  • \["从字面上匹配["
  • (第二个捕获组的开始
    • [^][]+匹配[]
    • 之外的任何内容
  • )捕获组结束
  • "\].*?SmsJob:最多匹配SmsJob:
  • (\w+)匹配单词字符序列并存储在第3个捕获组中

答案 3 :(得分:0)

对我来说,您的“ JOB-VARS”看起来非常像JSON。也许考虑使用JSON模块。

use strict;
use warnings;
use JSON;
my $json= new JSON;
while (<>) {
    my ($ts, $jtext)= /\[(.*?)\] production.DEBUG: JOB-VARS : (.*)/;
    my ($obj)= $json->decode_prefix($jtext);
    my $phone_number= $obj->{phone_numbers}->[0];
    my $jid= $obj->{objectKey};
    $jid=~ s/^.*://;
    printf "| %19s | %-15s |%32s|\n",$ts,$phone_number,$jid;
}