【问题标题】:Print string without sub-string in Perl在 Perl 中打印没有子字符串的字符串
【发布时间】:2015-05-14 19:59:14
【问题描述】:

我有一个格式如下的日志文件:

[Time] [mmm] [DATA] [rule] [a.a.a.a]
[Time] [ppp] [DATA] [rule] [a.a.a.a]
[Time] [mmm] [DATA] [rule] [c.c.c.c]

无法找到在没有特定子字符串的情况下打印此字符串的方法。我希望能够在没有匹配[mmm][a.a.a.a] 的子字符串行的情况下打印整个字符串输出。最终输出将是:

[Time] [ppp] [DATA] [rule] [a.a.a.a]  
[Time] [mmm] [DATA] [rule] [c.c.c.c]

我是使用带有两个子字符串的索引模块还是以某种方式使用 grep?我看错了吗?非常感谢任何帮助!!!

在我的 perl 脚本中,我有一个部分搜索此部分并将此部分打印为字符串:

sub Section
{
    my @event_rule = ("A", "B", "C");

    foreach (@event_rule)
    {
                    my $result1 = `fgrep -h 'DATA' $logfile1 | grep "$_" | head -n10`;
                    if (length $result1)
                    {
                        print "$result1\n";
            }
            }
  }

【问题讨论】:

  • 您的意思是“[mmm] 和 [a.a.a.a]”还是“[mmm] or [a.a.a.a]”?
  • @choroba 我认为是和。
  • 它的 [mmm] 和 [a.a.a.a] @choroba

标签: regex string perl


【解决方案1】:

不需要像grep这样的外部程序:

#!/usr/bin/perl
use warnings;
use strict;

my @rule  = ('[mmm]', '[a.a.a.a]');
my $regex = join '.*', map quotemeta, @rule; # Create one regular expression from the "rules".
$regex    = qr/$regex/;                      # Compile it.

my $c = 0;
while (<>) {
    $c += print if /DATA/ && ! /$regex/;
    last if $c > 9;                          # Only print the first 10 lines.
}

【讨论】:

    【解决方案2】:

    你可以使用

    grep -P "(?m)^(?!.*\[m{3}\].*\[a(?:\.a){3}\]).*$" file
    

    查看演示。

    https://regex101.com/r/mT0iE7/15

    【讨论】:

      【解决方案3】:

      您可以使用negative look ahead

      ^(((?!a.a.a.a).)*mmm((?!a.a.a.a).)*)$|^(((?!mmm).)*a.a.a.a((?!mmm).)*)$
      

      DEMO

      前面的正则表达式将匹配包含mmm 但不包含a.a.a.a 的字符串或包含a.a.a.a 但不包含mmm 的字符串。

      【讨论】:

        【解决方案4】:

        如果mmma.a.a的顺序相同,那么你可以使用下面的,

        grep -v '.*\[mmm\].*?\[a\.a\.a\.a\]' file
        

        如果您不知道顺序,请使用它。

        grep -P '^(?=.*\[mmm\])(?=.*?\[a\.a\.a\.a\]).+(*SKIP)(*F)|.+' file
        

        DEMO

        你可以在 perl 中使用相同的正则表达式,

        perl -lne 'print if /^(?=.*\[mmm\])(?=.*?\[a\.a\.a\.a\]).+(*SKIP)(*F)|.+/' file
        

        【讨论】:

          【解决方案5】:

          对于不使用mapgrep 的简单方法:

          use strict;
          use warnings;
          
          while(<DATA>){
              chomp;
              my @split = split(/\s+/);
              print "$_\n" unless ($split[1] eq '[mmm]' and $split[4] eq '[a.a.a.a]');
          }
          
          
          __DATA__
          [Time] [mmm] [DATA] [rule] [a.a.a.a]
          [Time] [ppp] [DATA] [rule] [a.a.a.a]
          [Time] [mmm] [DATA] [rule] [c.c.c.c]
          

          【讨论】:

            猜你喜欢
            • 2011-05-05
            • 2017-03-30
            • 2015-08-24
            • 1970-01-01
            • 1970-01-01
            • 2014-12-26
            • 1970-01-01
            • 1970-01-01
            • 2020-07-19
            相关资源
            最近更新 更多