我与模式匹配并获得使用$.
如何匹配Perl中模式匹配前后的行?
我所需要的特定的图在特定的模式后打印线匹配的匹配线,如:
line1
line2
line3
line4
line5
后,我的模式匹配line3
,我想打印line2
和line4
。
如何在Perl中进行模式匹配?谁能帮我?
在此先感谢
塞特希
我与模式匹配并获得使用$.
如何匹配Perl中模式匹配前后的行?
我所需要的特定的图在特定的模式后打印线匹配的匹配线,如:
line1
line2
line3
line4
line5
后,我的模式匹配line3
,我想打印line2
和line4
。
如何在Perl中进行模式匹配?谁能帮我?
在此先感谢
塞特希
你想要的东西通常被称为上下文。要获取上下文最简单的方法是自己一个变量保持它:
#!/usr/bin/perl
use strict;
use warnings;
my $old;
while (my $line = <DATA>) {
if ($line =~ /line3/) {
print "$old$line", scalar <DATA>;
last;
}
$old = $line;
}
__DATA__
line1
line2
line3
line4
line5
如果需要上下文的多条线路,最好是使用数组:
#!/usr/bin/perl
use strict;
use warnings;
my $context = shift || 3;
if ($context < 0) {
$context = 0;
}
my @old;
while (my $line = <DATA>) {
if ($line =~ /line6/) {
print @old, $line;
for (1 .. $context) {
print scalar <DATA>;
}
last;
}
push @old, $line;
#remove a line if we have more than we need
if (@old > $context) {
shift @old;
}
}
__DATA__
line1
line2
line3
line4
line5
line6
line7
line8
line9
我知道你问一个Perl的解决方案,但这里是一个Unix grep
解决反正:
grep -C 1 line3 file.txt
输出:
line2
line3
line4
从grep
手册页:
-C NUM, --context=NUM Print NUM lines of output context. Places a line containing -- between contiguous groups of matches.
但'grep'没有'perl'那样好的正则表达式引擎。为了简化'grep',但是'perl'正则表达式的威力,可以使用['ack'](http://search.cpan.org/dist/ack/ack-base)来代替:'ack - C 1 line3 file.txt' – 2010-09-04 13:28:53
要在Unix grep中使用Perl常规experssion语法,请使用'grep -P' – toolic 2010-09-04 14:26:58
随着标整个文件,写你的模式,以便它之前和之后line3
捕获线。 /m
modifier特别有用:
将字符串视为多行。即,将
^
和$
更改为匹配字符串的开头或结尾,以匹配字符串中任何位置的任何行的开头或结尾。
下面的模式使用/x
修饰符,它允许我们添加空格以使它们看起来像它们匹配的内容。
例如:
#! /usr/bin/perl
my $data = do { local $/; <DATA> };
my $pattern = qr/ ^(.+\n)
^line3\n
^(.+\n)
/mx;
if ($data =~ /$pattern/) {
print $1, $2;
}
else {
print "no match\n";
}
__DATA__
line1
line2
line3
line4
line5
输出:
line2 line4
记住$
是一个断言:它不会消耗任何字符,所以你必须匹配一个换行与文字\n
模式。
另请注意,上述模式缺乏一般性。它适用于中间某条线路,但如果将line3
更改为line1
或line5
,则该线路将失败。
对于line1
情况下,你可以把前行可选的一个?
量词:
my $pattern = qr/ ^(.+\n)?
^line1\n
^(.+\n)
/mx;
正如预期的那样,这产生
line2
输出但是,试图为line5
相同的修订案例
my $pattern = qr/ ^(.+\n)?
^line5\n
^(.+\n)?
/mx;
给出
no match
这是因为该文件中的最后的新行(所述一个以下line5
)后,^
无处可匹配,但改变图案
my $pattern = qr/ ^(.+\n)?
^line5\n
(^.+\n)?
/mx;
输出
line4
我们可能会在这里停止,但模式中的不对称性令人不快。为什么要为一个案件而不是另一个案件工作?与line1
,^
匹配$data
的开头,然后与(.+\n)?
什么都不匹配。
记住:模式与?
或*
总是量化成功,因为他们是在语义上一样
分别和什么都可以匹配零次:
$ perl -le 'print scalar "abc" =~ /(?!)*/' 1
虽然我不认为我见过它使用这种方式时,一个{m,n}
量词其中米为零,例如,
将总是成功,因为米是重复的最小数目。量词是一个包含完整性的病理案例。
所有这些都表明我们或多或少得到line1
的幸运。 ^
匹配的最开始,?
-量化模式没有匹配,然后下一个^
也匹配$data
的最开始。
恢复对称性使得清洁器模式:
my $pattern = qr/ (^.+\n)?
^line5\n
(^.+\n)?
/mx;
使用unix命令行功率大是这样的情况下和perl拥抱它。 尝试类似grep -A 1
或grep -B 1
它会给你之前/之前的行
噢,虽然上面的解决方案可以工作,但它们是非常难以编码的,并且在这种情况下不需要一个案例 – Noam 2010-09-04 12:20:08
到目前为止你有什么特点?如果更多的线路匹配呢?甚至有两条相应的线? – pavel 2010-09-04 09:35:37