我與模式匹配並獲得使用$.
如何匹配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