perl:如何删除两个模式之间的特定单词或模式

时间:2019-04-25 09:22:49

标签: regex perl multiline text-processing

我想使用perl在两种模式中删除一些单词

以下是我的文字

PQXY

现在,我想删除仅位于两个模式之间的所有^QWWK单词 KWWQ$perl -0777pe 's/^QWWK(?:(?!QWWK|KWWQ).)*KWWQ$/sometext/gms' filename

我知道如何通过以下命令替换两个模式之间的整个内容

^QWWK(?:(?!QWWK|KWWQ).)*KWWQ$

还请注意,LinearLayout此模式仅与之间没有QWWK和KWWQ的那些模式匹配。

4 个答案:

答案 0 :(得分:3)

您可以使用范围运算符:

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

答案 1 :(得分:2)

这是您尝试过的方法,仅需一点点工作即可

parseInt('5aab4') //5
// I expect the output is NaN.

perl -0777 -wpe's{^(QWWK (?:(?!QWWK|KWWQ).)*? KWWQ)$}{ $1 =~ s/PQXY//gr }egmsx' file modifier使其将替换面作为代码进行评估,然后在此处运行正则表达式。

在该正则表达式中,/e修饰符使其返回更改后的字符串(而不更改原始字符串,这使我们可以在只读的/r上运行它)。

上面的代码满足了$1^QWWK文本块中不包含上述任何一个短语的要求,但是一些注释可能会有所帮助。

我们不需要使用非贪婪的KWWQ$,因为.*?(遵循负前瞻)实际上停在.*。但这很难确定,KWWQ$才有可能将 all 包含到最后一个.*,包括所有其他可能的块以及它们之间的任何文本。

总而言之,我发现KWWQ更安全,更简单,特别是因为 是必需的。

.*?必须以一行(在问题中以QWWK开头)作为块的标记。如果在该块内找到额外的^,则整个块不匹配。但是,如果里面的“多余” QWWK恰好在一行的开头,那么

  • 本来应该是块的不匹配,因为里面有QWWK

  • 实际上是从那个 QWWK

  • 开始匹配一个块

我在上面使用了QWWK,以便能够隔开该模式以提高可读性。

答案 2 :(得分:1)

更新: 要仅在^ QWWK和KWWQ $之间不存在QWWK或KWWQ的情况下替换PQXY,请尝试以下操作:

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

我敢肯定它可以被清理/打高尔夫球,但是我认为它将满足您的要求。

答案 3 :(得分:1)

如果我正确理解了您的问题,则使用正则表达式以外的其他工具可能会更清楚。以下内容确实将单词之间的所有空白折叠为一个空格。

输入 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的{​​{1}}到行尾(($i==0 && $w eq q(QWWK))的{​​{1}}的{​​

单线

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了。)