如何在两场比赛之间排除正则表达式文本?

时间:2013-02-20 09:57:27

标签: regex perl batch-file

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

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: 

怎么可以这样做?

3 个答案:

答案 0 :(得分: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:的所有内容。

答案 1 :(得分:1)

/
   ^
   Filename: \s* \Q$myFileVar\E \n
   (?: (?!Message:) [^\n]*\n )*
   Message: \s* ([^\n]*) \n
   (?: (?!Time:) [^\n]*\n )*
   Time:
/mx

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

答案 2 :(得分:0)

Perl可以执行\K Magic

添加迟到的答案,因为我没有看到我最喜欢的解决方案。在Perl正则表达式中,\K告诉引擎放弃我们到目前为止匹配的所有内容。所以你可以使用这个正则表达式:

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

甚至:

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

请参阅demo