(シェルで)uniqコマンドを使用する場合、ファイルの形式を保持する方法は?

StackOverflow https://stackoverflow.com/questions/643143

質問

uniqコマンドを使用するには、最初にファイルをソートする必要があります。

しかし、私が持っているファイルでは、情報の順序が重要です。したがって、ファイルの元の形式を維持しながら重複したコンテンツを取り除くにはどうすればよいですか?

役に立ちましたか?

解決

別のawkバージョン:

awk '!_[<*>]++' infile

他のヒント

この awk は最初の出現を保持します。他の回答が使用するものと同じアルゴリズム:

awk '!(
sort file | uniq -d | awk '
   FNR == NR { dups[<*>] }
   FNR != NR && (!(<*> in dups) || !lines[<*>]++)
' - file
in lines) { print <*>; lines[<*>]; }'

awk を使用して、複製された行(すべての行ではなく)のみを保存する必要があるものを次に示します。

<*>

「行番号、二重ソート」もあります。メソッド。

 nl -n ln | sort -u -k 2| sort -k 1n | cut -f 2-

ファイルのソートされたバージョンでuniq -dを実行して重複行を見つけ、次のようなスクリプトを実行できます。

if this_line is in duplicate_lines {
    if not i_have_seen[this_line] {
        output this_line
        i_have_seen[this_line] = true
    }
} else {
    output this_line
}

uniqとgrepのみを使用:

d.shの作成:

#!/bin/sh
sort $1 | uniq > $1_uniq
for line in $(cat $1); do
cat $1_uniq | grep -m1 $line >> $1_out
cat $1_uniq | grep -v $line > $1_uniq2
mv $1_uniq2 $1_uniq
done;
rm $1_uniq

例:

./d.sh infile

次のような恐ろしいO(n ^ 2)を使用できます(擬似コード):

file2 = EMPTY_FILE
for each line in file1:
  if not line in file2:
    file2.append(line)

これは、特にBashレベルで実装されている場合は、かなり遅い可能性があります。ただし、ファイルがかなり短い場合、おそらく正常に機能し、実装は迅速になります( file2の行 grep -v などです) )。

それ以外の場合は、専用のプログラムをコーディングし、メモリ内のより高度なデータ構造を使用して高速化することもできます。

for line in $(sort file1 | uniq ); do
    grep -n -m1 line file >>out
done;

sort -n out

最初にソートを行います、

最初の一致(-m1)の各一意値grepについて

行番号を保持

出力を行番号で数値(-n)でソートします。

その後、sedまたはawkで#行を削除できます

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top