【问题标题】:How can I grep and sort text files using Perl?如何使用 Perl 对文本文件进行 grep 和排序?
【发布时间】:2010-09-24 02:46:17
【问题描述】:

我有一个非常混乱的简单日志文件,我需要它整洁。该文件包含日志标头,但它们都混杂在一起。因此我需要根据日志头对日志文件进行排序。没有固定的行数 - 这意味着文本文件的每个标题没有固定的行数。我正在使用 perl grep 来整理标题。

日志文件如下所示:

Car LogFile Header
<text>
<text>
<text>
Car LogFile Header
<text>
Car LogFile Header
<and so forth>

我已经完成/搜索了一个简单的算法,但它似乎不起作用。有人可以指导我吗?谢谢!

#!/usr/bin/perl

#use 5.010; # must be present to import the new 5.10 functions, notice 
#that it is 5.010 not 5.10


my $srce = "./root/Desktop/logs/Default.log";
my $string1 = "Car LogFile Header";
open(FH, $srce);
my @buf = <FH>;
close(FH);
my @lines = grep (/$string1/, @buffer);

执行代码后,终端没有显示结果。有什么想法吗?

【问题讨论】:

  • 好吧,如果你想显示结果,你必须输出一些东西。
  • 您先使用@buf,然后将其称为@buffer

标签: perl text grep


【解决方案1】:

我想你想要这样的东西:

 my $srce = "./root/Desktop/logs/Default.log";
 my $string1 = "Car LogFile Header";

 open my $fh, '<',  $srce or die "Could not open $srce: $!";

 my @lines = sort grep /\Q$string1/, <$fh>;
 print @lines;

确保您拥有正确的文件路径,并且该文件包含与您的测试模式匹配的行。

您似乎遗漏了很多非常基本的概念,并且可能会剪切和粘贴您在其他地方看到的代码。如果您刚刚开始,请学习 Perl 教程,例如 Learning Perlperlfaq2 中列出了其他书籍和参考资料。

【讨论】:

  • 我不明白为什么 $fh 处的“my”会导致系统现在给出此错误“全局符号“$scre”需要显式包名”,因为 $srce 应该没有问题。
  • @JavaNoob:因为“$scre”的拼写与“$srce”不同。
  • 哎呀.....没有注意到谢谢.. 但似乎代码只打印出标题而不是段落。我想一定是问题被问错了。无论如何它是正确的答案。
  • 提供一个简短的示例文件,然后准确地向我们展示您想要的输出。如果它不能满足您的需要,请不要接受这个答案。
【解决方案2】:

始终使用:

use strict;
use warnings;

这会告诉你@buffer 没有定义。

#!/usr/bin/perl

use strict;
use warnings;

my $srce = "./root/Desktop/logs/Default.log";
my $string1 = "Car LogFile Header";
open(my $FH, $srce) or die "Failed to open file $srce ($!)";
my @buf = <$FH>;
close($FH);
my @lines = grep (/$string1/, @buf);
print @lines;

Perl 对专家来说很棘手,因此专家使用它提供的警告来防止他们犯错。初学者需要使用警告,这样他们就不会犯他们甚至不知道自己会犯的错误。

(因为您没有机会chomp 输入行,所以末尾仍有换行符,因此print 每行打印一个标题。)

【讨论】:

  • 错误出现“readline() on closed filehandle $FH at ./rgex.pl line 9.”。对此有什么想法吗?
  • 如果你检查过 open() 的返回值,你就会发现这种情况。
  • 您使用的是什么版本的 Perl?对我来说效果很好,从答案中剪切'n'paste,使用 5.13.4、5.10.1、5.8.8。它在 5.6.2 中失败 - 找不到严格的位置,这有点令人费解...... OTOH,它是一个 PowerPC 构建的 Perl,运行在我运行 Snow Leopard(10.6.4)的(英特尔)Mac 上,我没有使用很久了。
【解决方案3】:

我不认为 grep 是你真正想要的。 正如您在布赖恩的回答中指出的那样,grep 只会给您标题,而不是后续行。

我认为您需要一个数组,其中每个元素都是标题,后续行到下一个标题。

类似:-

#!/usr/bin/perl

use strict;
use warnings;

my $srce = "./default.log";
my $string1 = "Car LogFile Header";
my @logs;
my $log_entry;
open(my $FH, $srce) or die "Failed to open file $srce ($!)";

my $found = 0;
while(my $buf = <$FH>)
{
    if($buf =~ /$string1/)
    {
        if($found)
        {
            push @logs, $log_entry;
        }

        $found = 1;
        $log_entry = $buf;
    }
    else
    {
        $log_entry = $log_entry . $buf; 
    }
}

if($found)
{
    push @logs, $log_entry;
}

close($FH);

print sort @logs;

我认为这是我们所要求的。

【讨论】:

    【解决方案4】:

    Perl grep 与 Unix grep 命令不同,它不会在屏幕上打印任何内容。

    一般语法是:grep Expr, LIST

    LIST 的每个元素计算Expr,并返回一个列表,该列表由表达式计算为true 的那些元素组成。

    在您的情况下,将返回所有具有 $string1 值的 @buffer 元素。

    然后您可以打印@buffer 数组以实际查看它们。

    【讨论】:

    • 他的意思是你不能只定义一个数组并期望从中得到屏幕输出。要获得屏幕输出,您必须 print 数组。
    【解决方案5】:

    您只是将所有内容存储在一个数组中,而不是打印出来。也没有必要将整个文件保存在内存中。您可以逐行读取和打印匹配结果,如下所示:

    my $srce = "./root/Desktop/logs/Default.log";
    my $string1 = "Car LogFile Header";
    open(FH, $srce);
    while(my $line = <FH>) { 
      if($line =~ m/$string1/) {
        print $line;
      }
    }
    close FH;
    

    【讨论】:

    • 仍然没有显示结果。它只是跳到终端中的一个空白行。
    • 不,试试你上面给出的日志文件文本。它将输出它可以找到的所有“Car Logfile Header”行。
    【解决方案6】:

    您好,我找到了一种从 html 文件中提取链接的方法

    !/usr/bin/perl -w

      2 
      3 # Links graber 1.0
      2 
      3 # Links graber 1.0
      4 #Author : peacengell
      5 #28.02.13
      6 
      7 ####
      8 
      9 my $file_links = "links.txt";
     10 my @line;
     11 my $line;
     12 
     13 
     14 open( FILE, $file_links ) or die "Can't find File";
     15 
     16 while (<FILE>) {
     17 chomp;
     18 $line = $_ ;
     19 
     20 @word = split (/\s+/, $line);
     21 @word  = grep(/href/, @word);
     22 foreach  $x (@word) {
     23 
     24 if ( $x =~ m /ul.to/ ){
     25 $x=~ s/href="//g;
     26 $x=~s/"//g;
     27 print  "$x \n";
     28 
     29                         
     30                         }
     31                 
     32                 }
     33         
     34         }
    

    你可以使用它并修改它如果你修改它请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-04
      • 2021-03-30
      • 1970-01-01
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      • 2013-04-23
      • 1970-01-01
      相关资源
      最近更新 更多