0

私は 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 (サーバー監視ツール) 用であり、特定の時間後に特定のサービスのユーザー定義コメントを削除する必要があります。

前もって感謝します!

4

2 に答える 2

2

いくつかの提案:

  • ネストされたループは、問題に対して適切な設計ではありません。必要なのは、ファイルを通過する 1 つのループで、その中にロジックが含まれています。
  • 等しいパラメーターを持つコメント ブロックは、常に対応するサービス ステータス ブロックの後にありますか? そうでない場合は、ファイルを 1 行ずつ処理する設計も再考する必要があります。
  • 例のように、ブロックは常に空白行で区切られていますか? もしそうなら、あなたは設定することができます$/ = "\n\n";。次に、行ごとではなくブロックごとにファイルを読み取ることができます。

ハッシュを使用して削除したいものを追跡する方法の例を次に示します。すべてのブロックが空白行で区切られているという仮定を使用していますが、そうでない場合は、ファイルを調べる池上の方法にこれを簡単に適応させることができます.

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
  }
于 2013-02-20T08:57:00.933 に答える
1

どうですか

my $file; { local $/; $file = <$fh>; }
while ($file =~ /^\s*(\S+)\s*\{([^}]*)\}/mg) {
   my $name  = $1;
   my $block = $2;
   ...
}
于 2013-02-20T08:50:59.427 に答える