【问题标题】:How can I print lines that match a pattern in Perl?如何打印与 Perl 中的模式匹配的行?
【发布时间】:2016-05-29 08:53:30
【问题描述】:

假设file.txt 每行只有一个句子如下:

约翰·德普是个好人。
他很聪明。
他什么都能做。
来见见约翰·德普。

Perl 代码如下:-

open ( FILE, "file.txt" ) || die "can't open file!";
@lines = <FILE>;
close (FILE);
$string = "John Depp";
foreach $line (@lines) {
    if ($line =~ $string) { print "$line"; }
}

输出将是第一行和第四行。

我想让它适用于具有随机换行符的文件,而不是每行一个英文句子。我的意思是它也应该适用于以下情况:-

约翰·德普是个好人。他非常聪明。他什么都能做。来见见约翰·德普。

输出应该是第一句和第四句。

有什么想法吗?

【问题讨论】:

  • 我最近才知道我自己做错了的一个潜在问题:当你做一个 die 语句时,它应该是“or die”而不是“|| die”,因为它们实际上有不同的优先级。在这种情况下它会起作用,因为只有一个语句,它不能与其他任何东西组合在一起。但无论如何你都应该在任何地方都使用“or die”。
  • @crimson 在这种情况下,由于open 调用中使用了括号,因此 OP 很好。一个更严重的问题是文件的完全不必要的啜饮。此外,die 消息应包括文件名和错误消息$!。此外,使用词法文件句柄和open 的三参数形式将使代码符合最佳实践。
  • 你当然是对的。我并没有真正看大部分代码,我只是看了一眼,就想把它扔进去。

标签: regex perl


【解决方案1】:

更简单:如果您假设“句子”由点分隔,那么您可以将其用作字段分隔符:

 $/ = '.';
 while(<>) {
        print if (/John Depp/i);
 }

【讨论】:

  • 这适用于简单示例,但如果其中一个句子指的是 Mr. John Depp。
  • 当然。但是,给定这个输入,你期望理想的 perl 代码输出什么? “约翰·德普是个了不起的人。他什么都能做。快来认识一下约翰·德普先生。他很聪明。” ?您是否期望 perl “知道”“来见见约翰·德普先生”。是一句话?怎么样?
  • 也就是说,我假设作者只是在寻找一个正则表达式解决方案(标记为“正则表达式”),在这种情况下,必须对句子的分隔方式做一些简单的假设。如果这还不够(在真正的英语中还不够),则必须求助于某个了解英语书面语言本质的图书馆-正如您所指出的那样(Lingua::Sentence)
【解决方案2】:

首先,注意著名演员的名字是Johnny Depp

其次,弄清楚什么是句子,什么不是句子是很棘手的。我要作弊使用Lingua::Sentence

#!/usr/bin/perl

use strict; use warnings;

use Lingua::Sentence;

my $splitter = Lingua::Sentence->new('en');

while ( my $text = <DATA> ) {
    for my $sentence ( split /\n/, $splitter->split($text) ) {
        print $sentence, "\n" if $sentence =~ /John Depp/;
    }
}

__DATA__
John Depp is a great guy.
He is very intelligent.
He can do anything.
Come and meet John Depp.
John Depp is a great guy. He is very intelligent. He can do anything. Come and meet John Depp.

输出:

约翰·德普是个好人。
来见见约翰·德普。
约翰德普是个好人。
来见见约翰·德普。

【讨论】:

    【解决方案3】:

    假设你的内容是一个字符串:

    my $content = "John Depp is a great guy.  
    He is very intelligent.  
    He can do anything.  
    Come and meet John Depp.";
    
    my @arr = $content =~ /.*John Depp.*/mg;
    foreach my $a (@arr) {
        print "$a\n";
    }
    

    结果:

    约翰·德普是个好人。
    来见见约翰·德普。

    如果您只想提取有趣的部分,您可以修改正则表达式,例如:

    my @arr = $content =~ /is (\w+? ?\w+ \w+)./mg;
    

    结果:

    一个好人

    非常聪明

    【讨论】:

      【解决方案4】:

      一种方式

      while(<>){
       if (/John Depp/i){
         @s = split /\s*\.\s*/;
         foreach my $line (@s){
            @f=split /\s*\.\s*/ , $line;
            foreach my $found (@f){
              if ($found =~/John Depp/i) {
                 print $found."\n";
              }
            }
         }
       }
      }
      

      输出

      $ cat file
      John Depp is a great guy.
      He is very inteligent.
      He can do anything.
      Come and meet John Depp.
      John Depp is a great guy. He is very inteligent. He can do anything. Come and meet John Depp.
      
      $ perl perl.pl file
      John Depp is a great guy
      Come and meet John Depp
      John Depp is a great guy
      Come and meet John Depp
      

      【讨论】:

      • 如果您的文件中有John\nDepp eats with scissors. 怎么办?
      • 有很多如果是对的呢?不要问我,问 OP。
      【解决方案5】:

      如果不小心,默认变量可能会被破坏。所以给所有东西命名是个好主意。

      这应该让你开始:

      #!/usr/bin/perl -w
      
      use strict;
      
      my $targetString = "John Depp";
      
      while (my $line = <STDIN>) {
          chomp($line);
          my @elements = split("\\.", $line);
          foreach my $element (@elements) {
              if ($element =~ m/$targetString/is) {
                  print trim($element).".\n";
              }
          }
      }
      
      sub trim {
          my $string = shift;
          $string =~ s/^\s+//;
          $string =~ s/\s+$//;
          return $string;
      }
      

      用法:

      $ depp.pl < file
      John Depp is a great guy.
      Come and meet John Depp.
      John Depp is a great guy.
      Come and meet John Depp.
      

      【讨论】:

        【解决方案6】:

        查看您的原始代码,而不是专门回答您的问题。除非必须,否则将整个文件读入内存通常是个坏主意。您可以将文件逐行处理为

        open ( FILE, "file.txt" ) || die "can't open file!";
        $string = "John Depp";
        while (<FILE>) {
           if (/$string/) { print }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-23
          • 1970-01-01
          • 2020-06-02
          • 2020-10-12
          • 2021-09-10
          相关资源
          最近更新 更多