3

まず、次の投稿で用語が間違っている場合は、申し訳ありませんが、これはまだ私にとって非常に新しいことです。

背景として、アーカイブされたネットワーク構成で特定の設定セットをチェックするスクリプトがあります。そのため、スクリプトはいくつかのチェックを実行し、そのチェックの結果を配列に追加します。

たとえば、syslogが構成されていることを確認するチェックが@internalsyslogerrorというアレイに追加されます

すべてのチェックが実行された後、すべてのチェックの配列がハッシュに追加されます。キーはデバイス名です。

すべてのコードが厳密に使用されていることに注意してください。警告を使用してください

次のコマンドで;

$results{$configs} = [@internalsyslogerror, @bordersyslogerror, 
@borderntperror, @borderntperror, @internalntperror, 
@bordertacacserror, @internaltacacserror, @enablepasswordchecks,
@internalsnmpkeyserror, @timezoneerror, @configregistererror, 
@bannererror, @bootregistererror, @domainnameerror];

私が抱えている問題は、この情報を抽出する最も洗練された方法です。スクリプトに新しいチェックを追加するために必要な変更の量を減らしたいと思います。現在、上記のコードに追加の配列を追加してから、それを処理するサブに間接参照部分を追加する必要があります。

これが現在、参照を解除して配列に出力し、それを電子メールで送信するために行うことです。

foreach my $k (keys %results) {
    push @results, "<b>$k</b><br>";
    if (defined $results{$k}[0] ){
    push @results, "$results{$k}[0]";
    }
    if (defined $results{$k}[1] ){
    push @results, "$results{$k}[1]";
    }
    if (defined $results{$k}[2] ){
    push @results, "$results{$k}[2]";
    }
    if (defined $results{$k}[3] ){  
    push @results, "$results{$k}[3]";
    }
    if (defined $results{$k}[4] ){
    push @results, "$results{$k}[4]";
    }
    if (defined $results{$k}[5] ){
    push @results, "$results{$k}[5]";
    }
    if (defined $results{$k}[6] ){
    push @results, "$results{$k}[6]";
    }
    if (defined $results{$k}[7] ){
    push @results, "$results{$k}[7]";
    }
    if (defined $results{$k}[8] ){
    push @results, "$results{$k}[8]";
    }
    if (defined $results{$k}[9] ){
    push @results, "$results{$k}[9]";
    }
    if (defined $results{$k}[10] ){
    push @results, "$results{$k}[10]";
    }
    if (defined $results{$k}[11] ){
    push @results, "$results{$k}[11]";
    }
    if (defined $results{$k}[12] ){
    push @results, "$results{$k}[12]";
    }
    if (defined $results{$k}[13] ){
    push @results, "$results{$k}[13]";
    }
}

問題は、上記で行っていることを実行できますが、どういうわけか「オンザフライ」でコードを生成できるかどうかです。

ありがとう

4

5 に答える 5

5
foreach my $k (keys %results) { 
   push @results, "<b>$k</b><br>"; 
   for my $result (@{$results{$k}) {
       next if (!defined $result);
       push @results, $result;
   }
}

あるいは

foreach my $k (keys %results) { 
   push @results, "<b>$k</b><br>"; 
   push @results, grep { defined $_ } @{$results{$k}};
}

編集:最後のプッシュでのタイプミスを修正しました...

于 2011-06-21T10:32:46.160 に答える
4

このスニペットが既存の動作を変更しないことを確認するのに十分なコードを見ていません。しかし、それは大丈夫なはずです。そしてそれは間違いなく保守性を向上させます:

foreach my $k (keys %results) {
    push @results, "<b>$k</b><br>";
    foreach my $index ( 0..$#{$results{$k}} ) {
        if (defined $results{$k}[$index] ){
            push @results, "$results{$k}[$index]";
        }
    }
}

上記は、foreach/if構文全体を置き換えます。

于 2011-06-21T10:31:48.823 に答える
3

forループを使用します。

for ($i = 0; $i < 14; $i++) {
  ...
}
于 2011-06-21T10:13:32.417 に答える
2

このコードは....機能不全のように私には見えます。私が間違っている場合は私を訂正してください。

$results{$configs} = [@internalsyslogerror, @bordersyslogerror, ... ];

これにより、配列の配列ではなく、スカラー値の1つの長い配列のみが作成されます。このことを考慮:

C:\perl>perl -we "@a=qw(1 2 3 a); @g=(11,22,33,44); $b{key}=[@a,@g]; print qq(@{$b{key}},\n); print qq($b{key}[0]);"
1 2 3 a 11 22 33 44,
1

これは、と$b{key}の両方のすべての値が含まれていること、および最初の配列の最初の値、つまりを参照していることを明確に示しています。@a@g$b{key}[0]$a[0]

ログを個別の変数に収集するという、あなたがしているように見えることを行うには、特定のキーの下で、配列参照を使用する必要があります。

$results{$config} = [\@internalsyslogerror, \@bordersyslogerror, ...];

現在のソリューションが機能していることを確認できる唯一の方法は、コードの前半にバグ/機能(意図的または意図的でない)があり、各配列の最初の値にそのカテゴリに関連するすべてのデータが含まれている場合です。

$internalsyslogerror[0] = "device A not responding, shutting down.\ndevice A rebooted.\nyada yada\n ....";

この場合、あなたがしていることは次のようになります。

$results{$config} = [ $internalsyslogerror[0], $bordersyslogerror[0], ...];

ただし、配列の1つで2つの値を取得する必要がある場合は、システムが台無しになり、レポートの最後に1つずつエラーが発生します。値に対して動的なforループを使用しない限りpush、それでも厄介です。

また、未定義の値を除外することにより、順序のみに依存する内部構造が台無しになり、の最初の値がまたは@resultsから来ているかどうかがわかりません。@internalsyslogerror@bordersyslogerror

結論:

現在のシステムが正常に機能していることに満足している場合は、他の人が提案しているように、単にforループを使用してください。絶対値ではなく動的値を使用します。私はFMcのソリューションが好きです(少し変更されています):

# Solution by FMc
for my $k (keys %results) {
    push @results, "<b>$k</b><br>";
    push @results, grep { defined $results{$k}[$_] } 0 .. $#results{$k};
}

ただし、内部構造を保持する場合は、未定義の値を除外することはできません。また、データが最初の配列値の文字列にすでに結合されていない限り、すべての異なる配列を1つに結合することはできません。それで:

$results{$config} = [ \@array1, \@array2, ...];

....

for my $key (keys %results) {
    push @results, "<b>$key</b><br>";
    my $i=0;
    for my $ref (@{$results{$key}]) {
        push @results, "Array $i:\n<br>" . (defined @$ref ? "@$ref" : "");
        $i++;
    }
}

出力のフォーマットも微調整できます。文字列結合の代わりに、たとえば"@array"、明示的な結合を行うことができますjoin("<br>\n", @array)

于 2011-06-21T11:11:51.883 に答える
1

キーを使用して何もしていない場合、これは同等です。

@results = map { "$_" } grep {; defined } map { @$_ } values %results;
于 2011-06-21T11:32:56.413 に答える