回答:
各同一行を任意の順序で1行だけ印刷するには:
sort -u
一意の行のみを任意の順序で印刷するには:
sort | uniq -u
各同一行を最初に出現した順序で1回だけ印刷するには、次のようにします(各行について、まだ表示されていない場合はその行を印刷し、その後、いずれの場合も表示されたカウンターをインクリメントします)
awk '!seen[$0] {print}
{++seen[$0]}'
一意の行のみを最初の出現順に印刷するには:(の各行を記録seen
しlines
、それが最初の出現の場合も入力します。入力の最後に、出現順に行のみを表示します一度)
awk '!seen[$0]++ {lines[i++]=$0}
END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'
awk '!seen[$0]++ {print}'
?
awk '!seen[$0]++'
、{print}
は空のコマンドによって暗示されるためです。
一部の(ほとんどの?)バージョンには、パーツを直接実行sort
する-u
フラグがありuniq
ます。ただし、実装によっては行の長さが制限される場合がありますが、既にplainで制限されていますsort|uniq
。
sort -u
少なくともV7に戻ります。
-u
、512文字の行長制限もあります。(実際には、Solaris 9 Sunのどこかで5120に引き上げられたと思います。しかし、GNUはまだ勝っています。)
Perlはあなたに合っていますか?複製が隣接していない場合でも、元の順序で行を維持できます。Pythonまたはでコーディングすることもできますawk
。
while (<>) {
print if $lines{$_}++ == 0;
}
これは短くすることができます
perl -ne 'print unless $lines{$_}++;'
与えられた入力ファイル:
abc
def
abc
ghi
abc
def
abc
ghi
jkl
出力は次のとおりです。
abc
def
ghi
jkl
use strict;
またはuse warnings;
(実際に、それはstrict
ここに最も関連性のあるもの)、使用についての苦情はありません%lines
、それが定義される前に。制限付きで実行する場合my %lines;
、ループの前に行が必要です。また、ハッシュは%lines
; であることに注意してください。ハッシュの1つの要素は、$lines{$_}
表記法を使用して参照されます。
sort
大量のデータの場合、ソリューションの方が優れていると思います(OPは「メモリにファイル全体を保存する」ことを懸念していました)。sort
データが利用可能なメモリよりも大きい場合、コア外ソートを実行します。
この質問への回答として、@ Gillesによる一意の行の印刷で言及した回答の最後の部分について、2つのハッシュを使用する必要性を排除しようとしました。
この解決策は次のとおりです:一意の行のみを最初に出現した順に印刷するには:
awk '{counter[$0]++}
END {for (line in counter) if (counter[line]==1) print line}'
ここで、「counter」には、前に処理された行と同様の各行のカウントが格納されます。
最後に、カウンタ値が1である行のみを印刷します。