【问题标题】:grep regex match and print more lines, but ignore print (or don’t match) if extra line includes a different patterngrep 正则表达式匹配并打印更多行,但如果额外行包含不同的模式,则忽略打印(或不匹配)
【发布时间】:2021-12-06 06:12:45
【问题描述】:

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

示例文本:

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.*$' * 将打印

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

但我不想在 第二个 group 上打印包含单词 elsewhere它的第三行。 使用 Perl 正则表达式。

【问题讨论】:

    标签: regex perl grep multiline


    【解决方案1】:

    您可以使用 GNU grep 之类的

    grep -oPzn '(?m)^.*?\bgloom\b(?!(?:.*\R){2}.*?\belsewhere\b)(?:.*\R){2}.*\R?' file > outputfile
    

    详情

    • -o - 输出匹配的文本,而不仅仅是发生匹配的行
    • z - 现在,换行符被吞并可以与正则表达式匹配
    • (?m)^ - 行首
    • .*? - 除换行符以外的任何零个或多个字符,尽可能少
    • \bgloom\b - 整个词gloom
    • (?!(?:.*\R){2}.*?\belsewhere\b)gloom字下面的第二行,不应该有elsewhere作为一个完整的字
    • (?:.*\R){2} - 当前行的其余部分、下一行和换行符
    • .*\R? - 带有可选换行符(序列)的整行(第二行)。

    online demo

    #!/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"
    

    【讨论】:

      【解决方案2】:

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

      #!/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 "$&";
      }
      

      See Perl Demo

      See Regex Demo

      如果您想在输入行中指定输入为来自标准输入或文件,那么:

      #!/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 "$&";
      }
      

      【讨论】:

        【解决方案3】:

        这是一个 Perl 的例子:

        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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多