簡體   English   中英

perl:如何刪除兩個模式之間的特定單詞或模式

[英]perl: how to remove particular word or pattern in between two patterns

我想用perl刪除兩個模式中的一些單詞

以下是我的文字

..........

QWWK jhjh  kljdfh jklh jskdhf jkh PQXY
lhj ah jh sdlkjh PQXY jha slkdjh 
PQXY jh alkjh ljk
kjhaksj dkjhsd KWWQ
hahs dkj h PQXY
.........

現在我想刪除所有僅位於兩種模式之間的PQXY單詞^QWWKKWWQ$

我知道如何通過以下命令替換兩個模式之間的整個事物

perl -0777pe 's/^QWWK(?:(?!QWWK|KWWQ).)*KWWQ$/sometext/gms' filename

另請注意^QWWK(?:(?!QWWK|KWWQ).)*KWWQ$此模式僅匹配中間沒有QWWK和KWWQ的模式。

您可以使用范圍運算符:

perl -pe 's/PQXY//g if /^QWWK/ .. /KWWQ$/'

這是你嘗試過的方法,它需要更多的工作

perl -0777 -wpe's{^(QWWK (?:(?!QWWK|KWWQ).)*? KWWQ)$}{ $1 =~ s/PQXY//gr }egmsx' file

/e 修飾符使它將替換方評估為代碼,並在那里運行正則表達式。

在該正則表達式中, /r修飾符使其返回已更改的字符串(並且不更改原始文件,允許我們在$1上以只讀方式運行它)。

上面的代碼滿足要求^QWWK KWWQ$文本塊不包含這些短語,但一些注釋可能會有所幫助。

我們不需要非貪婪.*? 因為.* (在負向前瞻之后)實際上停在了KWWQ$ 但是,這是棘手的確定,和.*只是要啜了所有到最后的潛力KWWQ ,包括所有其他可能的塊以及它們之間的任何文本。

總而言之,我才發現.*? 更安全,更簡單,特別是因為這所需要的。

QWWK必須開始一行(在問題中用^給出)作為塊的標記。 如果在塊內找到額外的QWWK ,則整個塊不匹配。 但是,如果那個“額外”的QWWK內部恰好位於一條線的開頭那么

  • 什么是塊不匹配,因為里面有QWWK

  • 塊其實是在匹配開始QWWK

我使用上面的/x ,以便能夠將模式空間化以便於閱讀。

更新:僅當^ QWWK和KWWQ之間不存在QWWK或KWWQ時替換PQXY $嘗試:

perl -pe 'if (/^QWWK/ .. /KWWQ$/) {s/PQXY//g if ! /.+QWWK/ && !/KWWQ.+/}' filename

我相信它可以清理/打高爾夫球,但我認為它會給你你所要求的。

如果我正確理解你的問題,除了正則表達式之外的其他工具可能會更清楚。 以下操作會將單詞之間的任何空格折疊為單個空格。

輸入 qwwk.txt (添加一行)

..........

QWWK jhjh  kljdfh jklh jskdhf jkh PQXY
lhj ah jh sdlkjh PQXY jha slkdjh
PQXY jh alkjh ljk
kjhaksj dkjhsd KWWQ
hahs dkj h PQXY
.........

KWWQ in mid line doesn't trigger: QWWK a PQXY b KWWQ c QWWK d PQXY e KWWQ

命令 perl qwwk.pl qwwk.txt

產量

..........

QWWK jhjh kljdfh jklh jskdhf jkh
lhj ah jh sdlkjh jha slkdjh
jh alkjh ljk
kjhaksj dkjhsd KWWQ
hahs dkj h PQXY
.........

KWWQ in mid line doesn't trigger: QWWK a PQXY b KWWQ c QWWK d PQXY e KWWQ

程序 qwwk.pl

use strict; use warnings;
while(<>) {             # for each line
    my @out;
    my @words=split;    # get its words

    for my $i (0..$#words) {
        my $w=$words[$i];
        my $active = ($i==0 && $w eq q(QWWK)) .. ($i==$#words && $w eq q(KWWQ));
            # Keep track of where we are.  See notes below.
        push @out, $w unless $active and ($w eq q(PQXY));
            # Save words we want to keep
    } #foreach word

    print join(q( ), @out), qq(\n);     # Print the words we saved
} #foreach line

關鍵是$active= FOO .. BAR賦值中的觸發器( .. )運算符保持其狀態,而不管它周圍發生了什么。 QWWK開始( ($i==0 && $w eq q(QWWK)) )到行尾的KWWQ($i==$#words && $w eq q(KWWQ)) ),無論干預多少行。

作為單線

perl -Mstrict -Mwarnings -ne 'my @out; my @words=split; for my $i (0..$#words) { my $w=$words[$i]; my $active = ($i==0 && $w eq q(QWWK)) .. ($i==$#words && $w eq q(KWWQ)); push @out, $w unless $active and ($w eq q(PQXY)); } print join(q( ), @out), qq(\n);' qwwk.txt

這里的區別在於-n提供while(<>){}循環,因此不包含在-e腳本中。 (另外,現在你知道為什么我在獨立程序中使用了q()qq() ;)。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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