regex - 使用 perl 插入可能缺失的行

标签 regex perl regex-lookarounds

我正在尝试修改 perl 过滤器以插入可能丢失的行。

我的输入可能是

一个

C

一个
C

A 和 B 是固定的并且是预先知道的。 C 可能因文件而异。

真实数据更复杂——调用堆栈作为 回归测试。取决于所使用的编译器(因此 优化)可能有尾调用消除可以删除 'B' 框架。过滤文件后简单地进行比较。

在第二种情况下,我想插入“B”行。在第一种情况下,我不想插入重复的行。我认为这是一个负前瞻的工作,使用以下内容

s/A.(?!B)/A\nB/s;

但这似乎意味着“如果 A.(?!B) 的任何部分与输入文本匹配,则将其替换为 A\nB”,而我需要“如果 A.(?!B) 的所有部分都匹配”,然后替换.

无论我尝试什么,它要么总是替代,要么从不替代。

最佳答案

在一行中准备好测试

perl -0777 -wpe's/ ^A.*\n \K (?!B.*\n) /B-line\n/xgm' file

\K 使它删除它之前的所有匹配项,因此我们不必在替换端捕获并复制它们。使用 -0777 switch整个文件被压缩成一个字符串,在 $_ 中可用。

为了匹配所有这样的 A-B?-C 行组,我们需要 /g modifier (匹配“全局”),为了使 anchor ^ 也匹配内部换行符,我们需要 /m 修饰符(“多行”)。

/x 修饰符使其忽略文字空格(以及换行符和注释),允许将内容分隔开以提高可读性。

另一方面,如果以 A 开头的行后面必须跟以 B 开头的行,或者以 C< 开头的行 如果 B 行不存在,那么它更简单,不需要先行

perl -0777 -wpe's/ ^A.*\n \K (^C.*\n) /B-line\n$1/xgm' file

这两个在我的(基本)测试中都能正常工作。

在任何一种情况下,文件的其余部分都按原样打印,因此如果需要,您可以使用 -i 开关“就地”更改输入文件,并使用 -i.bak 你也会得到一个备份。所以

perl -i.bak -0777 -wpe'...' file

或者您可以将输出(重定向)转储到同一个文件中以覆盖它,因为如果这用完了脚本,则会首先读取整个文件。


逐行读取文件当然要灵活得多。例如

use warnings;
use strict;
use feature 'say';

my $just_saw_A_line;

while (<>) { 
    if ($just_saw_A_line and not /^B/) { 
        say "B-line";
    }   

    $just_saw_A_line = /^A/;
    print
}

这也处理多个 A-(B?)-C 行组。它更容易根据变化进行调整。

该程序就像一个过滤器,从命令行给出的文件中获取 STDIN 或行,并将行打印到 STDOUT。然后可以将输出重定向到一个文件,但不能重定向到输入文件本身。 (如果需要更改输入文件,则需要为此修改代码。)

关于regex - 使用 perl 插入可能缺失的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62783334/

相关文章:

perl - 我可以使用 Log::Log4perl 将一些结果写入文件而不依赖于默认级别吗?

python - 使用 swig 包装自定义哈希表

java - 正则表达式问题 - 匹配 API 名称

.net - 如何过滤文件上传控件?

javascript - javascript 语言的正则表达式

java - 将字符串中的正则表达式模式替换为取决于匹配的替换字符串

c# - 用于解析重复组的正则表达式

regex - Jmeter - 提取 URL 和 BODY 中的查询字符串

perl - 在 perl 中使用 Getoptions 获取数组的输入

javascript - 正则表达式:仅当另一个单词不存在时才匹配单词