2016-11-29 78 views
1
@matches = ($filestr =~ /^[0-9]+\. (.+\n)*/mg); 

我有一个已经读入filestr文件,但出于某种原因,上述正则表达式,它应该匹配一行的开头,后跟一个数字,一个点,一个空格,然后是换行符之后的任何行数(因此在有只有换行符的行时结束)似乎只是从文件中产生一些单行。为什么没有这个Perl的正则表达式的工作

当我这样做

@matches = ($filestr =~ /^[0-9]+\. .+\n/mg); 

我正确匹配的单行。

当我这样做

@matches = ($filestr =~ /^[0-9]+\. .+\n.+\n/mg); 

我匹配相同的单线条,其次是一些看似无关的线。我的正则表达式有什么问题?

注意:正则表达式正常工作在这个正则表达式测试:https://regex101.com/,它只是不会在Perl中工作。

实施例,在这样的文字:

1. This should 
match 

2. This should too 

3. This 
one 
also 

正则表达式应该匹配

1. This should 
match 

2. This should too 

3. This 
one 
also 
+0

仅供参考:当换行符开始发挥作用,可以考虑使用',而不是'\ N' \ R'。但是,在这里你最好改变整个方法,逐行检查每一个后续的方法。 –

+0

感谢您的建议。我刚刚尝试过\ R,但我得到的结果与\ n相同。 –

+0

你知道一个很好的方法来按照你建议的方式逐行检查吗?看起来我基本上是手动拆分正则表达式。首先检查一行是否匹配^ [0-9] + \。 ,然后检查一行是否匹配。+ \ n用于第一行其余行和所有后续行(直到我得到一行只有一个换行符,此时我必须重新启动)。 –

回答

2

你的正则表达式是正确的。但是,你正在部分捕获结果。我建议你将整个比赛捕获到一个结果集中,这就是它将如何存储到@matches中。

所以,正确的正则表达式会变成/(^[0-9]+\. (?:.+\n)*)/gm。通过这种方式,您可以将匹配结果捕获到$1。将其包装成程序产量。

虽然它不会保留那些圆括号(...)也是因为默认情况下它需要$&(即整个匹配),除非您捕获任何内容。因此,请记住在这些情况下,您应该使用non-capturing group(?: ...)而不是捕获组()

#!/usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my $str = ' 
1. This should 
match 

2. This should too 

3. This 
one 
also 
'; 

my @matches = $str =~ /^([0-9]+\. (?:.+\n)*)/gm; 

print Dumper(\@matches); 

输出:

[ 
      '1. This should 
match 
', 
      '2. This should too 
', 
      '3. This 
one 
also 
' 
     ]; 
1

在这种情况下,您应该逐段阅读,而不是逐行阅读文件。为此,您需要将$/设置为空字符串。例如:

use strict; 
use warnings; 

my @result; 

{ 
    local $/ = ""; 
    while (<DATA>) { 
     chomp; 
     push @result, $_ ; 
     # or to filter paragraphs that don't start with a digit, use instead: 
     # push @result, $_ if /^[0-9]+\./; 
    } 
} 


__DATA__ 
1. This should 
match 

2. This should too 

3. This 
one 
also 
相关问题