web-dev-qa-db-ja.com

ファイルの各行の重複を削除します

たとえばここで、各行の重複を削除するにはどうすればよいですか?

1 1 1 2 1 2 3
5 5 4 1 2 3 3

この出力を取得したい:

1 2 3 
5 4 1 2 3

たくさんの行(100,000)があり、各行に一意の値が必要です。 Perlが最速かもしれませんが、PerlまたはBashでそれを行うにはどうすればよいですか?

7
Arash

Awkを使用するオプションは次のとおりです。

_awk '{ while(++i<=NF) printf (!a[$i]++) ? $i FS : ""; i=split("",a); print ""}' infile > outfile
_

編集コメントで更新:

  1. while (++i<=NF)

    $ 0はawkのフルラインであるため、whileループを初期化し、「i」をプリクリメントします。

    したがって、$ 1(最初のフィールド)から始まります。行を最後までループします(「フィールド数」のawkに組み込まれている「NF」以下)。デフォルトのフィールド区切り文字はスペースです。デフォルトの区切り文字は簡単に変更できます。

  2. printf (!a[$i]++) ? $i FS : ""

    これは 三項演算 です。

    したがって、入力が配列_!a[$i]++_にない場合は、$ iを出力し、ある場合は、 ""を出力します。 (この方法が気に入らない場合は、_!_を削除し、_$i FS : ""_を逆にすることができます)。

  3. i=split("",a)

    通常、これはnull分割です。この場合、次の行のためにIをリセットします。

  4. _print ""_

    出力の行を終了します(実際には100%の理由ではありません)。そうでない場合、次の出力になります。

    _1 2 3 5 4 1 2 3_の代わりに
    _1 2 3_
    _5 4 1 2 3_

12
nerdwaller

Rubyには、私が知っているLinuxディストリビューションが付属しているので:

_Ruby -e 'STDIN.readlines.each { |l| l.split(" ").uniq.each { |e| print "#{e} " }; print "\n" }' < test
_

ここで、testは要素を含むファイルです。

このコマンドの機能を説明すると、Rubyはほとんど左から右に読むことができますが、

  • 入力を読み取ります(シェルを介して_< test_から取得されます)
  • 入力の各行を通過します
  • アイテムを区切る1つのスペースに基づいて行を配列に分割します(split(" ")
  • この配列から一意の要素を(順番に)取得します
  • 一意の要素ごとに、スペースを含めて印刷します(_print "#{e} "_)
  • 固有の要素を使い終わったら、改行を印刷します
5
slhck

純粋なbashではありませんが...:

while read line; do
    printf "%s\n" $line | sort -u | tr '\n' ' '
    echo ''
done < file

行は副産物としてソートされます。

2
glenn jackman