2

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

这是我的代码:

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,一旦我得到该关键字,然后我必须以相反的方向读取文件,直到我得到 FATAL(仅限第一次遇到)。我在其他文件中打印这两个信息。

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

4

4 回答 4

8

不,您永远不会向后读取文件。至少在任何像这样简单的情况下都不会。您只需存储最后一次读取Fatal匹配并在找到时打印它eof

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

请注意,我删除了/gi您的正则表达式上的选项,因为它们在这里是多余的。您不想要不区分大小写的匹配,也不需要匹配多次。

于 2013-06-08T12:03:16.560 回答
1

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

perl -ne '$fatal=$_ if /Fatal/i; print $_,$fatal if /installd: eof/i' file > file_01
于 2013-06-08T12:22:10.260 回答
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;
      }
    }
  }
}
于 2013-06-08T12:32:00.900 回答
0

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

tac file.log|perl -ne'$eof=$_ if /eof/; print $eof,$_ and exit if $eof and /fatal/'
于 2017-06-25T21:17:58.243 回答