使用するのはawk
どうですか?あなたは本当に簡単に最初の出現を得ることができます:
[ghoti@pc ~]$ cat data1
./501.res/1.bin
./503.res/1.bin
./503.res/2.bin
./504.res/1.bin
[ghoti@pc ~]$ awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' data1
./501.res/1.bin
./503.res/1.bin
./504.res/1.bin
[ghoti@pc ~]$
最後のオカレンスを取得するには、いくつかの種類をパイプでつなぐことができます。
[ghoti@pc ~]$ sort -r data1 | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort
./501.res/1.bin
./503.res/2.bin
./504.res/1.bin
[ghoti@pc ~]$
「find」と「grep」を使用している場合、おそらくこれを行うことができます。
find . -name \*.bin -type f -print | sort -r | awk 'BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1' | sort
これはどのように作動しますか?
このfind
コマンドには、globでファイルを選択したり、ファイルの種類を選択したりする機能など、多くの便利なオプションがあります。既に知っている出力であり、それがへの入力になりsort -r
ます。
まず、入力データを逆に並べ替えます(sort -r
)。これにより、任意のディレクトリ内で、最も大きい番号のファイルが最初に表示されることが保証されます。その結果はawkに送られます。FSはフィールドセパレータであり、$2
「/ 501」、「/ 502」などになります。Awkスクリプトにはcondition {action}
、入力の各行に対して評価される形式のセクションがあります。条件が欠落している場合、アクションはすべての行で実行されます。「1」が条件でアクションがない場合は、行を出力します。したがって、このスクリプトは次のように分類されます。
a[$2] {next}
a
-添え字が$2の配列(つまり「/ 501」)が存在する場合は、次の行にジャンプします。さもないと...
{a[$2]=1}
-配列に添え字$2を1に設定します。これにより、将来、最初の条件がtrueと評価され、次に...
1
-行を印刷します。
このawkスクリプトの出力は、必要なデータになりますが、順序は逆になります。決勝戦sort
はあなたが期待する順序に物事を戻します。
さて...これは多くのパイプであり、何百万行もの入力を同時に処理するように要求すると、ソートは少しリソースを消費する可能性があります。このソリューションは、少数のファイルには完全に十分ですが、大量の入力を処理している場合は、お知らせください。オールインワンのawkソリューションを考え出すことができます(60秒以上かかります)書く)。
アップデート
デニスの賢明なアドバイスによると、上記に含めたawkスクリプトは、次のように変更することで改善できます。
BEGIN{FS="."} a[$2] {next} {a[$2]=1} 1
に
BEGIN{FS="."} $2 in a {next} {a[$2]} 1
これは機能的には同じですが、配列メンバーに値を割り当てるのではなく、配列メンバーを定義するだけでよいという利点があります。これにより、awkの実装によってはメモリやCPUを節約できます。とにかく、それはよりきれいです。