Perl正则表达式 - 需要忽略一个字符的前两个实例

时间:2016-02-19 12:12:21

标签: regex perl

我需要从以下字符串中提取message属性(即我想提取字符串“test”在文件中出现4次。)。

severity="warning" message="The String "test" appears 4 times in the file." source="com.puppycrawl.tools.checkstyle.checks.coding.MultipleStringLiteralsCheck"

我已尝试使用正则表达式message="([^"]*)",但这会在第一个出现时停止。The String在这种情况下会返回。

有没有办法忽略message属性中的内部引号并捕获整个属性?

3 个答案:

答案 0 :(得分:1)

如果属性始终按此顺序排列,即sourcemessage之后,您可能会尝试使其更加健壮

message="(.*?)"\s+source="

如果消息中出现source=,这将会中断。

答案 1 :(得分:1)

如果我们可以假设总是由字母数字或下划线符号(\w+组成),后跟=,并且vlaues不包含模式,您可以使用带有点.*?的延迟量词,并使用正lookehead检查尾随边界。因此,作为快速而肮脏的一次性修复,您可以使用

message="(.*?)"(?=\s+\w+=|$)

请参阅regex demo

请注意,.默认情况下与换行符号不匹配,您需要/s修饰符。

您需要修改输入。

答案 2 :(得分:1)

此解决方案不断从字符串中提取字符,直到遇到source=这样的新标签。所有参数值都存储在哈希%params中,因此message的值仅为$params{message}

我已经使用Data::Dump仅在解析字符串后显示完整的哈希内容

use strict;
use warnings 'all';
use feature 'say';

my $str = 'severity="warning" message="The String "test" appears 4 times in the file." source="com.puppycrawl.tools.checkstyle.checks.coding.MultipleStringLiteralsCheck"';

my %params;

while ( $str =~ / (\w+) \s* = \s* " ( (?: . (?! \w+ \s* = ) )* ) " /gsx ) {
    $params{$1} = $2;
}

say $params{message};

use Data::Dump;
dd \%params;

输出

The String "test" appears 4 times in the file.
{
  message  => "The String \"test\" appears 4 times in the file.",
  severity => "warning",
  source   => "com.puppycrawl.tools.checkstyle.checks.coding.MultipleStringLiteralsCheck",
}