首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >grep正则表达式匹配并打印更多行,但如果额外行包含不同的模式,则忽略打印(或不匹配)

grep正则表达式匹配并打印更多行,但如果额外行包含不同的模式,则忽略打印(或不匹配)
EN

Stack Overflow用户
提问于 2021-10-19 09:58:11
回答 3查看 141关注 0票数 1

我想使用grep和regex匹配一行的一部分,然后继续打印这一行和接下来的2行。但是,我不想打印任何匹配,在匹配后的第二行中,包含另一个正则表达式。

示例案文:

代码语言:javascript
复制
If the line was there is a loom in the gloom
would you want that line printed?
Just trying to understand if you're just
other than as part of gloom
if you really do want to exclude lines
even when loom appears on it's own elsewhere on the line

搜索模式,;使用grep -Pn -A2 '^.*\b(gloom)\b.*$' *将打印

代码语言:javascript
复制
If the line was there is a loom in the gloom
would you want that line printed?
Just trying to understand if you're just

..and

代码语言:javascript
复制
other than as part of gloom
if you really do want to exclude lines
even when loom appears on it's own elsewhere on the line

但我不想在第三行打印第二个,其中包含了这个词。使用Perl-regex。

EN

回答 3

Stack Overflow用户

发布于 2021-10-19 11:08:27

下面是Perl中的一个示例:

代码语言:javascript
复制
use v5.20.0;  # signatures requires perl >= 5.20
use feature qw(say);
use strict;
use warnings;
use experimental qw(signatures);

{
    my $lines = read_file('file.txt');
    for my $i (0..$#$lines) {
        my $line = $lines->[$i];
        if ($line =~/\b(gloom)\b/) {
            if (!match_second_pattern($lines, $i)) {
                print_block($lines, $i);
            }
        }
    }
}

sub print_block($lines, $i) {
    my $N = $#$lines;
    for my $j (0..2) {
        last if $i+$j > $N;
        print $lines->[$i+$j];
    }
}

sub match_second_pattern($lines, $i) {
    my $N = $#$lines;
    return 0 if ($i + 2) > $N;
    return $lines->[$i+2] =~ /elsewhere/;
}

sub read_file( $fn ) {
    open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
    my @lines = <$fh>;
    close $fh;
    return \@lines;
}
票数 1
EN

Stack Overflow用户

发布于 2021-10-19 11:44:14

这类问题通常是用负前瞻来解决的。不幸的是,我不相信您可以让命令行grep跨行边界向前看,因此这需要一个Perl程序来完成:

代码语言:javascript
复制
#!/usr/bin/perl
 
use strict;
 
my $s = "If the line was there is a loom in the gloom
would you want that line printed?
Just trying to understand if you're just
other than as part of gloom
if you really do want to exclude lines
even when loom appears on it's own elsewhere on the line";
 
while ($s =~ /^.*?\bgloom\b(?!.*\n.*\n.*?\belsewhere\b).*\n.*\n.*\n?/mg) {
    print "$&";
}

见Perl演示

见Regex Demo

如果希望在输入行中指定从stdin或文件输入的输入,则:

代码语言:javascript
复制
#!/usr/bin/perl -w
use strict;

my $s = '';
# read from stdin or the file specified on the command line:
while (<>) {
    $s .= $_ ;
}

while ($s =~ /^.*?\bgloom\b(?!.*\n.*\n.*?\belsewhere\b).*\n.*\n.*\n?/mg) {
    print "$&";
}
票数 1
EN

Stack Overflow用户

发布于 2021-10-20 11:13:13

您可以使用GNU grep,如

代码语言:javascript
复制
grep -oPzn '(?m)^.*?\bgloom\b(?!(?:.*\R){2}.*?\belsewhere\b)(?:.*\R){2}.*\R?' file > outputfile

详细信息

  • -o -输出匹配的文本,而不仅仅是发生匹配的行
  • z -现在,行分隔符被删除,并且可以与regex匹配。
  • (?m)^ -行的开始
  • .*? -除断行字符以外的任何零或多个字符,尽可能少。
  • \bgloom\b -全词gloom
  • (?!(?:.*\R){2}.*?\belsewhere\b)gloom单词下面的第二行,不应该有整个单词的elsewhere
  • (?:.*\R){2} -当前行的其余部分、下一行和一行中断
  • .*\R? -带可选行中断(序列)的整个(第二行)行。

在线演示

代码语言:javascript
复制
#!/bin/bash
s="If the line was there is a loom in the gloom
would you want that line printed?
Just trying to understand if you're just
other than as part of gloom
if you really do want to exclude lines
even when loom appears on it's own elsewhere on the line"
grep -oPzn '(?m)^.*?\bgloom\b(?!(?:.*\R){2}.*?\belsewhere\b)(?:.*\R){2}.*\R?' <<< "$s"
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69628776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档