【问题标题】:How can I search multiple files for a string in Perl?如何在 Perl 中搜索多个文件以查找字符串?
【发布时间】:2010-12-03 12:28:46
【问题描述】:

我的问题可能很简单,但我完全是新手。我想在多个文本文件的内容中搜索特定短语,然后在屏幕上显示找到的行。我已经学会了如何处理单个文件。例如,如果我想搜索一个单词,在 F 的根目录下名为“wyvern.txt”的文本文件中说“Okay”。以下代码有效:

#!/usr/bin/perl

$file = 'F:\wyvern.txt';
open(txt, $file);
while($line = <txt>) {
  print "$line" if $line =~ /Okay/;
}
close(txt);

但是如果我想在两个文本文件中搜索相同的短语,分别说“wyvern”和“casanova”,该怎么办?或者F的根目录下的“novels”目录中的所有文件如何.

任何帮助将不胜感激。 提前致谢

迈克

编辑:

哈哈,我终于想通了如何在目录中的所有文件中搜索模式匹配:) 以下代码效果很好:

#!/usr/bin/perl  
@files = <F:/novels/*>;
foreach $file (@files) {
open   (FILE, "$file");
while($line= <FILE> ){
print "$line" if $line =~ /Okay/;
}
close FILE; 
} 

【问题讨论】:

  • 你真的需要它在 Perl 中吗?如果你使用的是类 Unix 操作系统,你可以谷歌如何使用 grep。
  • 考虑到$file 中的路径,我认为它们不是

标签: perl


【解决方案1】:

扩展 Jonathan Leffler 提供的好答案:

找到匹配的文件名在$ARGV,稍作改动,行号可以在$.中找到。示例:

while (<>) {
  print "$ARGV:$.:$_" if /pattern/;
} continue {
  close ARGV if eof; # Reset $. at the end of each file.
}

此外,如果您有一个文件名列表并且它们不在命令行上,您仍然可以获得神奇的ARGV 行为。观看:

{
  local @ARGV = ('one.txt', 'two.txt');
  while (<>) {
    print "$ARGV:$.:$_" if /Okay/;
  } continue {
    close ARGV if eof;
  }
}

对于对一系列文件进行逐行处理(无论它是什么),这是一种普遍有用的模式——即使我可能会为此具体推荐File::GrepApp::Ack问题:)

【讨论】:

  • 谢谢小伙伴们!该代码完美运行,现在我可以在多个文件中搜索指定字符串:) --------------- #!/usr/bin/perl { local @ARGV = ('F:\ wyvern.txt', 'F:\casanova.txt'); while () { print "$ARGV:$.:$_" if /Okay/; } continue { 关闭 ARGV if eof; } } ------------ 但是如果我想搜索指定目录中的所有文件,我应该怎么做,比如“小说”中的开车 F?
  • 查看glob()获取某个目录下的文件,查看File::Find::ObjectFile::Find::Rule查找子目录下的文件。
  • 谢谢你,霍布斯!对于像我这样的初学者来说,事情似乎变得有趣了:)
【解决方案2】:

在命令行参数被正确扩展的系统上,您可以使用:

[sinan@host:~/test]$ perl -ne 'print "$.:$_" if /config/' * 1:$(srcdir)/config/override.m4

Windows 的问题是:

C:\Temp> perl -ne "print if /perl/" *.txt 无法打开 *.txt:参数无效。

在 Windows 上,您可以这样做:

C:\Temp> for %f in (*.txt) do perl -ne "print if /perl/" %f

但是,您可能只想使用 cmd.exe 内置 findstrgrep 命令行工具。

【讨论】:

  • 如何使用 Windows perl 代码并将输出写入文本文件而不是终端? ...感谢这个非常有用的代码。
【解决方案3】:

最简单的方法是在命令行中列出文件,然后简单地使用:

while (<>)
{
    print if m/Okay/;
}

【讨论】:

    【解决方案4】:

    File::Grep 是你需要的

    【讨论】:

    • File::Grep 的文档对于新手来说太紧凑了,你可能知道初学者的教程吗?
    【解决方案5】:

    只是对你的行稍作调整:&lt;F:/novels/*&gt;,我更喜欢使用glob 关键字——它在这种情况下的工作方式相同,并且避免了混淆 perl 中尖括号的许多不同用法的机会。即:

    @files = glob "F:/novels/*";

    请参阅perldoc glob 了解更多信息。

    【讨论】:

      【解决方案6】:

      将文件放在 for 循环中,或者类似的东西:

      for $file ('F:\wyvern.txt','F:\casanova.txt') {
      
      open(TXT, $file);
      while($line = <txt>) {
           print "$line" if $line =~ /Okay/;
          }
      close TXT;
      }
      

      【讨论】:

      • @Lazy Bob,我将 ($line = ) 更改为 ($line = ) 并再次重新测试了代码。它工作得很好。感谢分享代码。
      【解决方案7】:

      好吧,我完全是个傻瓜。但总而言之,我现在可以在一个文本文件或多个文本文件中搜索指定的字符串。我仍在尝试弄清楚如何处理一个文件夹中的所有文件。 以下代码有效。

      代码1:

      #!/usr/bin/perl
      $file = 'F:\one.txt';
      open(txt, $file);
      while($line = <txt>) {
        print "$line" if $line =~ /Okay/;
      }
      close(txt);
      

      代码2:

      #!/usr/bin/perl
      {
        local @ARGV = ('F:\wyvern.txt', 'F:\casanova.txt');
        while (<>) {
          print "$ARGV:$.:$_" if /Okay/;
        } continue {
          close ARGV if eof;
        }
      }
      

      再次感谢您的帮助。我真的很感激。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        • 2015-03-20
        • 2014-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        相关资源
        最近更新 更多