0

CSV ファイルの列 9 ~ 13 にデータ (IP アドレス) があります。他の列に値がない場合、デフォルトでは、列 9 にあるものだけを出力する必要があります。一連の値と列 9 の値を出力する出力ファイルがあります (値がある場合は 13 まで)。存在する) を静的な値と連結してエイリアス値を作成します。私の質問は、これをどのように効率的に行うかということです。私は動作するこのコードを持っています:

my $alias0= "ComponentAliases=['ComputerSystem:$columns[9]'];\n";
my $alias1= "ComponentAliases=['ComputerSystem:$columns[9]','ComputerSystem:$columns[10]'];\n";
my $alias2= "ComponentAliases=['ComputerSystem:$columns[9]','ComputerSystem:$columns[10]','ComputerSystem:$columns[11]'];\n";


        print BAROC "ComputerSystem;\n";
        if(($columns[11] != '')&&($columns[10] != '')) {  print BAROC $alias2 }
        elsif(($columns[11] == '')&&($columns[10] != '')) {  print BAROC $alias1 }
        elsif(($columns[11] == '')&&($columns[10] == '')) { print BAROC $alias0 }

これは私がやりたいことを行うために機能しますが、CSV ファイルの列 9 ~ 13 または 9 ~ 11 などに値が含まれる可能性があります。ベスト プラクティスを理解し、常に適用します。私は Perl のスクリプトを作成するのは初めてですが、職場の問題を解決するために Perl に常に惹かれています。提案?

これは出力です、ところで:

ComponentAliases=['ComputerSystem:10.1.0.225','ComputerSystem:10.200.252.77','ComputerSystem:10.100.252.77'];
4

3 に答える 3

1
#!/usr/bin/env perl

use strict;
use warnings;

use Text::CSV_XS;

my $csv_in = Text::CSV_XS->new
    or die Text::CSV_XS->error_diag;

my $csv_out = Text::CSV_XS->new({
    always_quote => 1,
    quote_char => q{'},
}) or die Text::CSV_XS->error_diag;

while (my $row = $csv_in->getline(\*DATA)) {
    my @aliases = map "ComputerSystem:$_",
                  grep defined && length, @$row[9 .. 13];
    if ($csv_out->combine(@aliases)) {
        printf "ComponentAliases=[%s];\n", $csv_out->string;
    }
}

__DATA__
0,1,2,3,4,5,6,7,8,10.1.0.225,10.200.252.77,,,,,,,
0,1,2,3,4,5,6,7,8,10.1.0.225,10.200.252.77,10.100.252.77,,,,,

出力:

C:\temp> gn
ComponentAliases=['ComputerSystem:10.1.0.225','ComputerSystem:10.200.252.77'];
ComponentAliases=['ComputerSystem:10.1.0.225','ComputerSystem:10.200.252.77','Co
mputerSystem:10.100.252.77'];
于 2013-03-20T22:05:01.800 に答える
1

効率的に現在は保守可能を意味します。コマンドを 1 つまたは 2 つ保存しようとしても、多くの時間を節約することはできません。実際、コンパイラが何をしているのかを理解できない場合、実際にはプログラムの効率が低下する可能性があります。

重要なのは読みやすさです。ものを取り除き$aliasます。コードが何を行っているかを確認するのが難しくなるだけで、このようなことを行うあらゆる種類の副作用が発生する可能性があります。

また、空白が不足していると、コードを理解するのがはるかに難しくなります。コードを再フォーマットしたら、すぐにエラーを見つけました。あなたはこれをしました:

if ( ($columns[11] != '') && ($columns[10] != '') )

ただし、これは文字列比較です。これを行う必要があります:

if ( ( $columns[11] ne '' ) && ( $columns[10] ne '' ) ) {

または、さらに単純化することもできます。

if ( not $column[10] and not $column[11] ) {

これにより、何を探しているかが非常に明確になり、列に数字のゼロ、null 文字列、または未定義のいずれが含まれていても機能します。

このコード スニペットはロジックを使用していますが、文字列の末尾にprinta が自動的に追加されないという事実を利用しています。\n私は単に次の行に基づいて構築を続けます。

if ( $columns[9] ) {
    print BAROC "ComputerSystem;\n";
    print BAROC "ComponentAliases=['ComputerSystem:$columns[9]'";

    if ( $columns[10] ) {
         print BAROC ",ComputerSystem:$columns[10]";
    }
    if ( $columns[11] )  {
        print BAROC ",ComputerSystem:$columns[11]";
    }
    print BAROC "];\n";
}

これらの列にデータが含まれている場合、列 9 から 13 が必要になる可能性があると述べました。なぜループを使わないのですか?

if ( $#columns >= 9 ) {    #There are at least nine columns
    print BAROC "ComputerSystem;\n";
    print BAROC "ComponentAliases=[ComputerSystem:$columns[9]";

    for my $column ( (10..$#columns) ) {
       last if not $column[$column];
       print BAROC ",ComputerSystem:$columns[$columns];
    }
    print BAROC "];\n";
}

もっと時間があれば、ロジックをもう少しクリーンアップできると確信しています。ただし、これは、データが含まれる列が 9、10、11、または 43 のいずれであっても機能します。

于 2013-03-20T23:05:36.547 に答える
0

ワンライナー(それほどエレガントではありませんが、どういうわけか私はそれが好きです):

print "ComponentAliases=[".join(",",map {"'ComputerSystem:$_'"} grep {$_ ne ""} @columns[9-13])."]\n";

または、同じコードをよりわかりやすい方法で使用したい場合は、次のようにします。

print(  
        "ComponentAliases=[",
        join(
            ",",
            map(    
                "'ComputerSystem:$_'",
                grep (
                        $_ ne "",
                        @columns[9-13]
                     )
               )
            ),  
        "]\n"
     );  
于 2013-03-20T21:09:52.847 に答える