[英]Omitting or excluding Regular Expression matches from a Perl script
嗨,我想在文件中搜索類似於以下內容的內容:
Start Cycle
report 1
report 2
report 3
report 4
End Cycle
....繼續..
我想搜索“開始周期”,然后從中拉出報告1和報告3。我的正則表達式看起來像這樣
(Start Cycle .*\n)(.*\n)(.*\n)(.*\n)
上面的正則表達式選擇Start Cycle和接下來的三行。但是我想從結果中省略第三行。 那可能嗎? 還是可以完成任何更簡單的perl腳本? 我期望得到這樣的結果:
Start Cycle
report 1
report 3
以下代碼顯示Start Cycle
和End Cycle
之間的奇數行:
foreach (<$filehandle>) {
if (/Start Cycle/ .. /End Cycle/) {
print if /report (\d+)/ and $1 % 2;
}
}
您可以在開始標記和結束標記之間找到文本,然后按行分割上下文。 這是示例:
my $text = <<TEXT;
Start Cycle
report 1
report 2
report 3
report 4
End Cycle
TEXT
## find text between all start/end pairs
while ($text =~ m/^Start Cycle$(.*?)^End Cycle$/msg) {
my $reports_text = $1;
## remove leading spaces
$reports_text =~ s/^\s+//;
## split text by newlines
my @report_parts = split(/\r?\n/m, $reports_text);
}
也許是一種瘋狂的方式:改變Perl對輸入記錄的理解。
$/ = "End Cycle\n";
print( (/(.+\n)/g)[0,1,3] ) while <$file_handle>;
正則表達式使用每對方括號的內容填充$ 1,$ 2,$ 3和$ 4。
因此,如果只看$ 1,$ 2和$ 4的內容,您就會擁有所需的內容。
另外,您也可以不放在第三行。
您的正則表達式應該看起來像
/Start Cycle\n(.+)\n.+\n(.+)\n.+\nEnd Cycle/g
/ g允許您反復評估正則表達式,並且每次都始終獲得下一個匹配項。
如果您希望保留所有周圍的代碼不變,但是停止捕獲第三件事,則只需刪除導致捕獲該行的括號:
(Start Cycle .*\n)(.*\n).*\n(.*\n)
我將OP的問題作為Perl練習,並提出了以下代碼。 它只是出於學習目的而編寫的。 如果有任何可疑之處,請糾正我。
while(<>) {
if(/Start Cycle/) {
push @block,$_;
push @block, scalar<> for 1..3;
print @block[0,1,3];
@block=();
}
}
另一個版本(編輯並感謝@FM):
local $/;
$_ = <>;
@block = (/(Start Cycle\n)(.+\n).+\n(.+\n)/g);
print @block;
更新:我最初沒有注意到這只是@FM的回答 ,形式更加健壯和更長。
#!/usr/bin/perl
use strict; use warnings;
{
local $/ = "End Cycle\n";
while ( my $block = <DATA> ) {
last unless my ($heading) = $block =~ /^(Start Cycle\n)/g;
print $heading, ($block =~ /([^\n]+\n)/g)[1, 3];
}
}
__DATA__
Start Cycle
report 1
report 2
report 3
report 4
End Cycle
輸出:
Start Cycle report 1 report 3
while (<>) {
if (/Start Cycle/) {
print $_;
$_ = <>;
print $_;
$_ = <>; $_ = <>;
print $_;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.