簡體   English   中英

從Perl腳本中省略或排除正則表達式匹配項

[英]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 CycleEnd 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM