コマンドラインとスクリプトでのawkによる重複排除

コマンドラインとスクリプトでのawkによる重複排除

次の形式のファイルがあります:

487422,Potenza
487386,Forlì-Cesena
487399,Grosseto
487425,Catanzaro
487409,Napoli
487446,Prato
495498,Fermo
487425,Catanzaro
487389,Macerata
487442,Biella
487351,Asti
487424,Cosenza
487404,Roma
487359,Como
487404,Roma
487401,Terni
487420,Brindisi
487397,Arezzo
487348,Vercelli
487382,Modena
487356,Genova
487365,Cremona
487369,Verona
487386,Forlì-Cesena

ご覧のとおり、これは重複のあるコンマ区切りのテキストです。 を使用して、列 1 に関してテキストの重複を排除したいと思いますawk

コマンドライン

シェルインターフェースを使用すると、次のようになります

487422,Potenza
487386,Forlì-Cesena
487399,Grosseto
487425,Catanzaro
487409,Napoli
487446,Prato
495498,Fermo
487389,Macerata
487442,Biella
487351,Asti
487424,Cosenza
487404,Roma
487359,Como
487401,Terni
487420,Brindisi
487397,Arezzo
487348,Vercelli
487382,Modena
487356,Genova
487365,Cremona
487369,Verona

これは次のコマンドから期待されるものです

awk -F"," '!a[$1]++' filename.csv

Awk スクリプト

次のように書かれたawkスクリプトを使用すると

#!/bin/awk -f

BEGIN {
    FS=","
}
{
    {!a[$1]++}
}

出力が得られません。スクリプトに何か問題がありますか? スクリプトとコマンド ラインの動作が異なるのはなぜですか?

答え1

歯列矯正器具の外側に!a[$1]++状態{print}は、 true (ゼロ以外) と評価された場合にデフォルトのアクションをトリガーします。

中括弧の内側に{{!a[$1]++}}アクションこれは副作用なしで無条件に評価されます。中括弧を削除します。

#!/bin/awk -f

BEGIN {
    FS=","
}

!a[$1]++

答え2

@steeldriver の awk の回答これは正しく、おそらく必要なすべてですが、入力が大量になるとメモリが不足したり、比較的遅くなったりする可能性があります。その場合、引き続き機能する decorate/sort/undecorate アプローチを以下に示します。

nl -w1 -s, file |       # Decorate by prefixing with line numbers
sort -ut, -k2,2 |       # Sort uniquely by the real key field
sort -nt, -k1,1 |       # Sort whats left by the line numbers we added
cut -d, -f2-            # Undecorate by removing the line numbers

関連情報