【问题标题】:Perl - reading through command output file line by linePerl - 逐行读取命令输出文件
【发布时间】:2013-12-26 02:05:20
【问题描述】:

我有一个日志文件,其中包含在每台服务器上运行的多个命令的输出。格式是这样的

APRHY01> lt all
131119-15:41:39 10.105.219.68 10.0b  stopfile=/tmp/27599
Checking MOM version...RNC_NODE_MODEL_M_1_200
Parsing MOM (cached): /home/ekisjay/moshell//jarxml/RNC_NODE_MODEL_M_1_200.xml.cache.gz Done.
.............
.
.
.
APRHY01> alt
131119-15:41:55 10.105.219.68 10.0b RNC_NODE_MODEL_M_1_200 stopfile=/tmp/27599
Connecting to 10.105.219.68:56834 (CorbaSecurity=OFF, corba_class=2, java=1.6.0_26, jacoms=R73D19, jacorb=R73D01)
Starting to retrieve active alarms
Nr of active alarms are: 3

APRHY01> strt
131119-15:41:58 10.105.219.68 10.0b RNC_NODE_MODEL_M_1_200 stopfile=/tmp/27599

Following 326 sites are up:
---------------------------------------------------------------------------------------------------------------------
 MOD  IUBLINK    CELLNAMES        CFRPHEM1 CFRPHEM2 CFRPHEM3 CFRPHEM4 CFRPHEM5 CFRPHEM6 ICDS   TN ATMPORTS
---------------------------------------------------------------------------------------------------------------------
  21  Iub_00023  UHYD494-X        111111                                                1  1    I
  21  Iub_00032  UHY4100-X        111111                                                1  1    I

那么对于下一个服务器或节点重复此操作...

APRHY02> lt all

131119-15:44:51 10.105.219.4 10.0b  stopfile=/tmp/2874
Checking MOM version...RNC_NODE_MODEL_M_1_200
Parsing MOM (cached): /home/ekisjay/moshell//jarxml/RNC_NODE_MODEL_M_1_200.xml.cache.gz Done.
Using paramfile /home/ekisjay/moshell//commonjars/pm/PARAM_RNC_M_1_50.txt
Parsing
 file /home/ekisjay/moshell//commonjars/pm/PARAM_RNC_M_1_50.txt ...

我必须在每个节点的每个命令之间使用几行(根据要求中所述的条件)。我编写了一个 perl 程序,逐行读取并在与/[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\> 之类的命令匹配的每一行处停止,然后检索下一个命令行之间所需的行并将其写入另一个文件。在循环中,我的程序实际上跳过了一个命令并执行下一个命令(第 1、第 3、第 5 种......)。谁能帮帮我?

【问题讨论】:

    标签: perl file


    【解决方案1】:

    也许以下内容会有所帮助:

    use strict;
    use warnings;
    
    my ( $fileName, $fh, $i );
    
    while (<>) {
        if ( !$fileName or $fileName ne $ARGV ) {
            $fileName = $ARGV;
            $i        = 0;
        }
    
        if ( my ($cmd) = /^([A-Z]{5}\d{2}>.+)/ ) {
            $cmd =~ s/\W+/_/g;
            open $fh, '>', $cmd . '_' . ( sprintf '%05d', ++$i ) . '.txt' or die $!;
        }
    
        print $fh $_;
    }
    

    命令行用法:&gt;perl script.pl logFile1 [logFile2 .. logFileN]

    [ ] 表示法表示可选的多个文件。

    脚本使用正则表达式来捕获命令/服务器行,然后用下划线替换“非单词”字符,这加上一个计数加上 .txt 成为写入该命令文本块的文件名。因此,使用您的数据集,创建了以下包含命令内容的文本文件:

    APRHY01_lt_all_00001.txt
    APRHY01_alt_00002.txt
    APRHY01_strt_00003.txt
    APRHY02_lt_all_00001.txt
    APRHY02_alt_00002.txt
    APRHY02_strt_00003.txt
    

    插入计数只是为了防止向同一服务器多次发出相同的命令,因为这个数字确保每个文件都有单独的文件。

    【讨论】:

      【解决方案2】:

      你没有向我们展示你用来解析文件的代码,所以很难说它可能有什么问题:-)

      要像这样分解多行日志输出,一个好方法是遍历文件,将行附加到一个文本块,直到找到下一个块的第一行 - 然后刷新你的块一直在追加并创建一个新的,从当前行开始。

      my $block = "";
      while (<>) {
          if (/[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/) {
              write_block($block) if $block;
              $block = "";
          }
          $block .= $_;
      }
      write_block($block);
      

      【讨论】:

      • code: my $srcFile = "new.log";my $destFile = "deviations.log";my grabbed = {};my $line = "";open (my $src, " $srcFile") or die "Could not open the log file $srcFile: $!";open (my $dest, ">>$destFile") or die "Could not open the destination file $destFile: $!";while ($line = ){ if ($line =~ /[AZ][AZ][AZ][AZ][AZ][0-9][0-9]\>/) { 推抓, "命令输出的偏差:$line\n"; while ($line = ){if ($line !~ /[AZ][AZ][AZ][AZ][AZ][0-9][0-9]\>/){推抓, $line;}else{last;}}}}print $dest "\nrabbed";close $dest;close $src;
      • 考虑将代码添加到原始问题中,以便其他阅读者尝试回答。请准确复制并粘贴您遇到问题的代码,以确保问题不会被任何转录错误所混淆(例如 grabbed 用于 $grabbed)。
      • 当您的脚本遇到文件的第一行时,会发生匹配并将空字符串传递给write_block()
      • @kenosis 很公平,通过检查 $block 的计算结果为 true 很容易解决。
      【解决方案3】:

      你的

      代码:

      my $srcFile = "new.log";
      my $destFile = "deviations.log";
      my @grabbed = {};
      my $line = "";
      open (my $src, "$srcFile") or die "Could not open the log file $srcFile: $!";
      open (my $dest, ">>$destFile") or die "Could not open the destination file $destFile: $!";
      while ($line = <$src>)
      { if ($line =~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
        { push @grabbed, "Deviations of the output of command: $line\n";
          while ($line = <$src>)
          {if ($line !~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
           {push @grabbed, $line;
           }
           else
           {last;
      } } }}
      print $dest "\n@grabbed";
      close $dest;
      close $src;
      

      在查找新命令行时执行last 时,转到外部while ($line = &lt;$src&gt;),从而已经读取下一行(命令的第一个输出行)并且无法识别命令的开头。一个简单的解决方法是通过标记外部循环并使用redo 而不是last 来省略读取新行:

      LINE:
      while ($line = <$src>)
      { if ($line =~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
        { push @grabbed, "Deviations of the output of command: $line\n";
          while ($line = <$src>)
          { if ($line !~ /[A-Z][A-Z][A-Z][A-Z][A-Z][0-9][0-9]\>/)
            { push @grabbed, $line }
            else
            { redo LINE }
      } } }
      

      【讨论】:

        猜你喜欢
        • 2020-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多