Perlで列の合計を含む新しい列を追加します。

Perlで列の合計を含む新しい列を追加します。

次の列を含む巨大なテキストファイルがあります。

col1 col2 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
abc dec 10 20 30 40 50 60 70 80 90 11 12 13

私が探している出力は、FullYearという新しい列にすべての月を追加することです。

col1 col2 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec FullYear
abc dec 10 20 30 40 50 60 70 80 90 11 12 13 486

私はawkコマンドを試しましたが、データの精度は非常に高いです。以下のコマンドは誤った出力を提供します。

awk -F ' ' {print $1" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "$10" "$11" "$12" "$13" "$14" "$3+$4+$5+$6+$7+$8+$9+$10+$11+$12+$13+$14}' inputfile.txt > outputfile.txt

これを行うには、Perlスクリプトを作成する必要があります。

ベストアンサー1

Perlでは、1行のコードでこれを行うのはとても簡単です。

perl -MList::Util=sum -anE 'if (1 == $.) { say join(q{ }, @F, q{FullYear}) } else { say join(q{ }, @F, sum(@F[2..13])) }' «YOUR-FILE»

説明する:

-MList::Util=sumList::Util モジュールをロードしてsum関数をインポートします。これはと同じですuse List::Util qw(sum)

-nPerlに入力ファイルを1行ずつ処理し、各行に対してスクリプトを実行するように指示します。 (次のオプションが暗黙的に有効になるため、実際には重複します。)-a自動分割モードをオンにすると、@Fフィールドごとに1つの項目を持つ配列が作成されます。-Eつまり、現在のPerl関数(この場合は「馬」)を使用して、コマンドライン引数でスクリプトを提供するという意味です。

これらのオプションの詳細については、perlrunマンページ/ podfileで確認できます。

その後、スペースが追加され、コメントの説明が追加されたスクリプトは次のようになります。

if (1 == $.) {                        # $. is the line number. Line 1 is header line.
    say join(' ', @F, q{FullYear});   # print out the heder + FullYear
}
else {
    # print out rows + sum of columns 2..13. Remember Perl counts from 0 in arrays,
    # so column 2 is the 3rd column (the number for January).
    say join(' ', @F, sum(@F[2..13]));
}

注:Perlに、1行のコード(少なくとも信頼できる1行のコード - 信頼できないスクリプトでは安全ではありません)を理解するのに役立つように依頼することができます。次のような-MO=Deparse出力があります。

注文する:

perl -MO=Deparse -MList::Util=sum -anE 'if (1 == $.) { say join(q{ }, @F, q{FullYear}) } else { say join(q{ }, @F, sum(@F[2..13])) }' t-file 

出力:

use List::Util (split(/,/, 'sum', 0));
use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
LINE: while (defined($_ = readline ARGV)) {
    our @F = split(' ', $_, 0);
    if (1 == $.) {
        say join(' ', @F, 'FullYear');
    }
    else {
        say join(' ', @F, &sum(@F[2..13]));
    }
}
-e syntax OK

List::Utilしたがって、負荷を確認し、-n1行ずつ実行して-aからsplit

おすすめ記事