如何在perl中以相反的方向读取文件

时间:2013-06-08 11:56:29

标签: perl

我正在尝试编写我正在搜索关键字的脚本。一旦我得到该关键字,我必须回溯文件,我的意思是我必须开始以相反的方向读取文件,直到我得到所需的行。

这是我的代码:

use strict;
use warnings;
open(my $f1,"<","$file") or die "can not open the file $!\n";
open(my $f2,">","$file_01") or die "can not open the file $!\n";
my @eof =<$f1>;

    for(my $i=0;$i<=$#eof;$i++)
      {
         my $line=$eof[$i];
          if($line=~ m/installd: eof/gi)
         {
            print $line $f2;
            my $j=$i;
            for($j;$j<=0;$j--)
            {
            my $back_line=$eof[$j];
             if($back_line=~ m/Fatal/gi)
              {
                print $back_line $f2;
                exit;
              }
            }
          }
              }

这是日志:

06-05 16:37:43.903   274   404 E ThermalEngine: algo_monitor: Timer EVT
06-05 16:37:43.903   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-POPMEM Read pop_mem 53000mC, Err 27000mC, SampleCnt 5
06-05 16:37:43.903   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU3 Read cpu3 54000mC, Err 36000mC, SampleCnt 5
06-05 16:37:43.903   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU2 Read cpu2 54000mC, Err 36000mC, SampleCnt 5
06-05 16:37:43.903   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU1 Read cpu1 57000mC, Err 33000mC, SampleCnt 5
06-05 16:37:43.903   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU0 Read cpu0 63000mC, Err 27000mC, SampleCnt 5
06-05 16:37:43.903   274   404 E ThermalEngine: settimer: Start timer 0.325(sec)
06-05 16:37:43.903   274   404 E ThermalEngine: algo_monitor: Wait for EV
06-05 16:37:43.943 16232 16232 D StatusBar.NetworkController: onDataActivity: direction=0
06-05 16:37:43.943 16232 16232 D StatusBar.NetworkController: refreshViews connected={ data } level=4 combinedSignalIconId=0x7f020138/com.android.systemui:drawable/stat_sys_signal_4 combinedActivityIconId=0x0 mobileLabel=AIRCEL wifiLabel= emergencyOnly=false combinedLabel=AIRCEL mAirplaneMode=false mDataActivity=0 mPhoneSignalIconId=0x7f020138 mQSPhoneSignalIconId=0x7f02005f mDataDirectionIconId=0x7f020113 mDataSignalIconId=0x7f020138 mDataTypeIconId=0x7f020113 mQSDataTypeIconId=0x7f020061 mNoSimIconId=0x0 mWifiIconId=0x0 mQSWifiIconId=0x0 mBluetoothTetherIconId=0x1080563
06-05 16:37:43.943 16232 16232 D StatusBar.NetworkController: changing data overlay icon id to 0
06-05 16:37:43.953 16090 16091 F libc    : **Fatal signal** 11 (SIGSEGV) at 0x5f106dc8 (code=1), thread 16091 (SurfaceFlinger)
06-05 16:37:44.243   274   404 E ThermalEngine: algo_monitor: Timer EVT
06-05 16:37:44.243   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-POPMEM Read pop_mem 53000mC, Err 27000mC, SampleCnt 5
06-05 16:37:44.243   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU3 Read cpu3 54000mC, Err 36000mC, SampleCnt 5
06-05 16:37:44.243   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU2 Read cpu2 54000mC, Err 36000mC, SampleCnt 5
06-05 16:37:44.243   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU1 Read cpu1 57000mC, Err 33000mC, SampleCnt 5
06-05 16:37:44.243   274   404 E ThermalEngine: handle_timer_sig: SS Id SS-CPU0 Read cpu0 63000mC, Err 27000mC, SampleCnt 5
06-05 16:37:44.243   274   404 E ThermalEngine: settimer: Start timer 0.325(sec)
06-05 16:37:44.243   274   404 E ThermalEngine: algo_monitor: Wait for EV
06-05 16:37:44.263   262   262 I DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
06-05 16:37:49.193   256   256 I ServiceManager: service 'audio' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'network_management' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'textservices' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'netstats' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'netpolicy' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'wifip2p' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'uimode' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'dropbox' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'cneservice' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'country_detector' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'connectivity' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'servicediscovery' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'throttle' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'updatelock' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'commontime_management' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'devicestoragemonitor' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'notification' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'search' died
06-05 16:37:49.193   256   256 I ServiceManager: service 'location' died
06-05 16:37:49.213  8379  8379 W AudioFlinger: power manager service died !!!
06-05 16:37:49.213  8379  8379 W AudioFlinger: power manager service died !!!
06-05 16:37:49.213   300  1913 I Atfwd_Sendcmd: AtCmdFwd : binderDied
06-05 16:37:49.223   300  1913 I ServiceManager: Waiting for service AtCmdFwd...
06-05 16:37:49.233   268   268 E **installd: eof**
06-05 16:37:49.233   268   268 E installd: failed to read size
06-05 16:37:49.233   268   268 I installd: closing connection
06-05 16:37:49.233   268   268 I installd: new connection
06-05 16:37:49.243 30568 30588 I SystemServer: Entropy Mixer
06-05 16:37:49.283 30568 30588 I QCOM PowerHAL: QCOM power HAL initing.
06-05 16:37:49.283 30568 30588 I SystemServer: Power Manager

在上面的日志中我正在搜索:EOF首先我获得该关键字然后我必须以相反的方向读取文件,直到我得到致命(仅第一次遇到)。我在其他文件中打印这两个信息。

对我来说似乎逻辑是正确的但是在运行这个程序时我遇到了错误。我们有另一种方法来执行此任务吗?

4 个答案:

答案 0 :(得分:8)

不,你永远不会向后读文件。至少在任何情况下都不如此简单。您只需存储上次阅读的Fatal匹配,并在找到eof时将其打印出来:

my $fatal;
while (<>) {
    if (/Fatal/) {
        $fatal = $_;          # store line for later
    }
    if (/installd: eof/) {
        print $fatal;         # stored line
        print $_;             # current line
    }
}

请注意,我删除了regexges上的/gi选项,因为它们在这里是多余的。您不需要不区分大小写的匹配,并且您不需要多次匹配。

答案 1 :(得分:1)

它将始终保存最后的致命线,并将其与当前与eof匹配的行一起打印,

perl -ne '$fatal=$_ if /Fatal/i; print $_,$fatal if /installd: eof/i' file > file_01

答案 2 :(得分:0)

除了不必要的复杂性之外,还有三个问题会阻止程序正确且干净地运行

  • 您没有声明和定义$file$file_01

  • print $line $f2应为print $f2 $line

  • for ($j; $j <= 0; $j--) { ... }应该是for (; $j >= 0; $j--)(比较相反,提及$j本身就是多余的,可能会产生警告

此版本的代码运行良好,但却是错误的解决方案!

use strict;
use warnings;

@ARGV = qw/ logfile.txt outfile.txt /;

my ($file, $file_01) = @ARGV;

open(my $f1, '<', $file)    or die "can not open the file: $!";
open(my $f2, '>', $file_01) or die "can not open the file: $!";

my @eof = <$f1>;

for my $i (0 .. $#eof) {
  my $line = $eof[$i];
  if ($line =~ m/installd: eof/) {
    print $f2 $line;
    my $j = $i;
    while (--$j >= 0) {
      my $back_line = $eof[$j];
      if ($back_line =~ m/Fatal/) {
        print $f2 $back_line;
        exit;
      }
    }
  }
}

答案 3 :(得分:0)

如果日志文件很大,那么使用“tac”会更快。如果模式出现在底部附近,则在Linux中执行命令。对面的猫。它以相反的顺序列出了这些行。如果有多个/ eof / pattern,它也会找到last / eof / pattern:

tac file.log|perl -ne'$eof=$_ if /eof/; print $eof,$_ and exit if $eof and /fatal/'
相关问题