【问题标题】:Perl regex over multiple lines多行的 Perl 正则表达式
【发布时间】:2019-11-15 15:50:57
【问题描述】:

我有 2 个输入文件。

$> cat file1.txt
! This is a comment in file1.txt
// Another comment and below line is an empty line

SIR 8 
    TDI(03)
    TDO(01)
    MASK(03);

$> cat file2.txt
! This is a comment in file2.txt
// Another comment and below line is an empty line

sir 8 tdi(03) tdo(01) mask(03);

现在,我正在尝试编写一个脚本来收集所有这些“先生”台词。这就是我所拥有的:

while(<>) {
    # Skip over all lines that start with ! or are empty or start with //
    next unless !/^!/ and !/^\s*$/ and !/^\s*\/\//;

    # I'm using the modifier /i to be case insensitive
    if(/sir\s+\d+\s+tdi\(\d+\)\s+tdo\(\d+\)\s+mask\(\d+\)\s*;/i) {
        print $_;
    }
}

现在匹配单行的 file2.txt,但不匹配多行的 file1.txt。我搜索了很多并尝试了建议的修饰符 /m /s 和 /g 但没有运气。请问你能帮我找到正确的语法吗?

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    您一次读取一行并与之匹配,因此您不可能匹配跨越多行的内容。

    通过取消定义$/,一次读取整个文件是最简单的。

    local $/;
    
    while (<>) {
        while (/^sir\s+\d+\s+tdi\(\d+\)\s+tdo\(\d+\)\s+mask\(\d+\)\s*;/mig) {
            print "$&\n";
        }
    }
    

    /m 使^ 匹配行首。

    if (//) 替换为while (//g) 可以让我们获得所有匹配项。


    作为一个单行,

    perl -0777ne'CORE::say $& while /^SIR[^;]*;/mig'
    

    Specifying file to process to Perl one-liner

    【讨论】:

    • 这个正则表达式比你使用的那个短:SIR[^;]+;
    • @Federico Piazza,是的,但添加 ^ 对读者来说意义重大。它还可以防止注释掉的行匹配,这是 OP 感兴趣的。它还需要 SIR; 之间的东西,这很奇怪。最后,它还阻止XSIR 匹配(但不是SIRX)。使用^SIR\b 防止SIRX 匹配。简而言之,这不是一场高尔夫比赛。
    • @ikegami 非常感谢! next unless 行不再起作用(它现在删除了一些 SIR 行)但没关系,我还没有尝试修复它。但是还有另一种情况仍然无法正常工作。 SIR 8\n TDI(0000\n0000\n0000)\n...,基本上是当 TDI() 跨越多行时。最近几天我尝试了很多东西,但没有找到优雅的方法。如果您也能在这方面帮助我,我将不胜感激。谢谢,阿米尔
    • 如果括号仍然打开,阅读更多行直到它关闭。
    • 您的意思是附加if() 语句?我希望在while(/^sir.../) 中有一些东西或一个魔法修饰符来实现这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多