1

我有一组特定的重复文本块。它们具有动态文件名和动态消息。对于我要提取消息的每个文件名。

Filename: dynamicFile.txt
Property: some property to neglect
Message: the message I want
Time: dynamicTime

我想在消息之后提取部分,这将是:the message I want.

我所拥有的:以下内容将匹配文件名和时间之间的任何内容。

(?<=Filename: %myFileVar%)(?s)(.*)(?=Time:)

%myFileVar%动态文件变量是我将使用的表达式。

现在我需要找到一种方法来省略文件名之后的任何内容,直到消息部分。在这里我不得不省略:

Property: some property to neglect
Message: 

怎么可能做到这一点?

4

3 回答 3

2
use warnings;
use strict;

my $text;
{
    local $/;
    $text = <DATA>;
}

my $myFileVar = 'dynamicFile.txt';

if ($text =~ /Filename: \Q$myFileVar\E.*?Message: (.*?)\s*Time:/s)
{
   print $1;    
}

__DATA__
Filename: dynamicFile.txt
Property: some property to neglect
Message: the message I want
Time: dynamicTime

注意:这假设Time:总是紧跟在消息行之后。如果这不是真的,ikegami 的解决方案提供了一种跳过任何其他行的方法。

解释:

  • 您可以简单地将一个变量插入到您的模式中,它将被插值。
  • 但是,如果变量包含任何特殊的正则表达式字符,它们将被视为正则表达式字符。因此,您需要用 包围变量\Q...\E,这使得介于两者之间的所有内容都被逐字处理。如果您不这样做,则文件名中的点将匹配任何字符。
  • 您不需要使用环视来仅捕获字符串的一部分。取而代之的是,使用捕获组——模式中的任何正常括号集都将自动放入变量$1,$2等中。
  • 对于像这样的简单情况,最好在模式之后启用单行模式 ( s) 作为开关。(/s而不是(?s))。在模式中打开它是实验性的,仅当您需要它仅应用于模式的一部分时才应使用它。
  • .*?应该使用而不是.*. 否则,该模式将匹配文件中从第一个Message:到最后一个Time:的所有内容。
于 2013-02-20T10:05:28.720 回答
1
/
   ^
   Filename: \s* \Q$myFileVar\E \n
   (?: (?!Message:) [^\n]*\n )*
   Message: \s* ([^\n]*) \n
   (?: (?!Time:) [^\n]*\n )*
   Time:
/mx

(?: [^\n]*\n )*跳过任意数量的行。

于 2013-02-20T10:07:40.387 回答
0

Perl can do \K Magic

Adding a late answer because I'm not seeing my favorite solution. In Perl regex, \K tells the engine to drop everything we have matched so far from the final match. So you could have used this regex:

(?sm)^Filename:.*?Message: \K[^\r\n]+

or even:

(?m)^Message: \K[^\r\n]+

See demo.

于 2014-06-27T11:37:24.360 回答