ファイルから重複した行を削除しますが、1つのエントリは保持します。

ファイルから重複した行を削除しますが、1つのエントリは保持します。

ファイルから重複した行を削除したいのですが、ファイルに1つの項目を保持したいと思います。

ファイルの例:

this is a string
test line
test line 2
this is a string

上記の例では、「これは文字列です」という1つの項目を削除したいと思います。

これを行う最良の方法は何ですか?

答え1

デモファイルには以下stuff.txtが含まれます。

one
two
three
one
two
four
five

行の並べ替えが気に入らないとし、ファイルから重複行を削除します。

$ sort -u stuff.txt 
five
four
one
three
two

説明:ソートのために送信されるuフラグは、ファイルの行をソートして一意性を強制することを意味します。

最初の行を維持しながら元の順序を維持しながら、ファイルから重複行を削除します。

$ cat -n stuff.txt | sort -uk2 | sort -nk1 | cut -f2-
one
two
three
four
five

説明:catに渡されたnフラグは、各行の左側に行番号とスペースを追加します。最初のソートは一意のソートを意味しますが、最初の単語の後にのみ対応し、2番目のソートコマンドは私たちを使用することを意味します。ステップ1で保存した内容は元の順序で保存する必要があり、最終的に最初の単語が切り捨てられました。

ファイルから重複した行を削除して順序を維持し、最後の行を維持します。

tac stuff.txt > stuff2.txt; cat -n stuff2.txt | sort -uk2 | sort -nk1 | cut -f2- > stuff3.txt; tac stuff3.txt > stuff4.txt; cat stuff4.txt
three
one
two
four
five

説明:以前と同じですが、tacはファイルを反転して目的の結果を得ます。

答え2

最後の項目だけを残してすべてを削除することは、最初の項目だけを残してすべてを削除するのとは反対なので、次の回避策もあります。

tac file | awk '! seen[$0]++' | tac

tacファイルの行を逆にし、重複した行がawk最初に表示される部分のみを出力します。

答え3

あなたの意見に基づいて別の出力を生成したり、新しいファイルに追加しなくても結果が同じ出力ファイルになるようにするには、次のようにします。

例:

gawk -i inplace '!a[$0]++' $file

答え4

vimを使用している場合は、次のコードを試してみてください。

g/./if(temp == getline('.')) | let temp = getline('.') | else | :norm dd | endif

関連情報