逐块读取文件

时间:2013-02-20 08:44:52

标签: perl nagios

我正在使用perl并想要读取具有以下结构的外部文件(帖子末尾的完整代码):

servicestatus {
  parameter1 = abc
  parameter2 = abc
  parameter3 = abc
  }

servicecomment {
  parameter1 = def
  parameter2 = abc
  parameter3 = ghi
  }

这些块位于文件的不同部分,状态块位于上部,而注释块位于下部。 (每个评论栏与某个状态栏相关)

现在我正在尝试逐行扫描文件,所以我首先遇到一个状态块,读取某个参数(即参数2),最后搜索文件的其余部分以查找具有等参数。

我编写的用于解决此问题的脚本是非常嵌套的,除此之外它只找到第一个状态块,其对应的注释块然后离开循环,尽管还有更多要查找的内容。任何考虑这个问题的帮助都是受欢迎的!

这是完整的代码

while ($line = <SF>) {
  if ($line =~ /servicestatus/) {
    while ($line = <SF>) {
      if ($line =~ /service_description/) {
        $service_desc = $line;
        while ($line = <SF>) {
          if ($line =~ /servicecomment/) {
            while ($line = <SF>) {
              if ($line =~ /service_description/) {
                $service_desc2 = $line;
                if ($service_desc eq $service_desc2) {
                  while ($line = <SF>) {
                    if ($line =~ /comment_id/) {
                      if ($line =~ m/(\d+)/) {
                        $comment_id = $1;
                        while ($line = <SF>) {
                          if ($line =~ /entry_time/) {
                            if ($line =~ m/(\d+)/) {
                              $entry_time = $1;
                              if ($entry_time < $time_oldest) {

                                # Kommando wird in die Commandpipe geladen
                                open(CP, ">>$o_commandpipe") or die("nagios.cmd not found");

                                # Befehl wird ausgegeben, External Command DEL_SVC_COMMENT wird ausgeführt
                                print {CP} "[$time_now] DEL_SVC_COMMENT;$comment_id;$time_now\n";
                                close(CP);
                                print("Comment $comment_id deleted.\n");
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

close SF;

为了更好地理解:此脚本适用于nagios(服务器监视工具),并应在特定时间后删除某些服务的用户定义注释。

提前感谢!

2 个答案:

答案 0 :(得分:1)

怎么样

my $file; { local $/; $file = <$fh>; }
while ($file =~ /^\s*(\S+)\s*\{([^}]*)\}/mg) {
   my $name  = $1;
   my $block = $2;
   ...
}

答案 1 :(得分:1)

一些建议:

  • 嵌套循环不适合您的问题。你需要的是一个遍历文件的循环,里面有逻辑。
  • 具有相等参数的注释块是否始终位于其相应的服务状态块之后?如果没有,您还需要重新考虑逐行浏览文件的设计。
  • 块是否总是用空行分隔,如示例所示?如果是这样,您可以设置$/ = "\n\n";。然后你可以逐块而不是逐行读取文件。

以下是如何执行此操作的示例,使用哈希来跟踪要删除的哈希值。我假设所有块都用空行分隔,但如果不是这样,你可以很容易地将它改编为ikegami的浏览文件的方法。

use warnings;
use strict;

{
    my %delete_params;
    local $/ = "\n\n";
    while (<DATA>)
    {
        if (/^servicestatus/ and /parameter2 = (.*)/)
        {
            $delete_params{$1}++; #Delete comments with this parameter.
        }
        elsif (/^servicecomment/ and /parameter2 = (.*)/ and 
               exists $delete_params{$1})
        {
            next;   #Comment matched; do not print.
        }

        print $_;
    }   
}

__DATA__
servicestatus {
  parameter1 = abc
  parameter2 = abc
  parameter3 = abc
  }

servicestatus {
  parameter1 = abc
  parameter2 = xyz
  parameter3 = abc
  }

servicecomment {
  parameter1 = def
  parameter2 = abc
  parameter3 = ghi
  }

servicecomment {
  parameter1 = def
  parameter2 = xyz
  parameter3 = ghi
  }

servicecomment {
  parameter1 = def
  parameter2 = rrr
  parameter3 = ghi
  }