web-dev-qa-db-ja.com

重複行を示すuniq

$ grep home american.txt | sort | uniq                                                                                            
A home and a country should leave us no more!                                                                                        
Between their loved home and the war's desolation!                                                                                 
O'er the land of the free and the home of the brave!                                                                                  
O'er the land of the free and the home of the brave!                                                                                  
O'er the land of the free and the home of the brave?     

なぜこれは2つの重複した行を示しているのですか?

grep home american.txt | cat -Aの出力は次のとおりです。

O'er the land of the free and the home of the brave?^M$
O'er the land of the free and the home of the brave!^M$
A home and a country should leave us no more! ^M$
O'er the land of the free and the home of the brave!^M$
Between their loved home and the war's desolation!^M$
O'er the land of the free and the home of the brave!$
3
WinMacLinUser

自由の国と勇者の故郷です!

上記の行は3回出現します。最初の2つのオカレンスは、どちらも最後にキャリッジリターンがあります。 3回目はそうではありません。次のコマンドを使用して視覚化できます。

猫-American.txt

これは、このテキストファイルの最後に空の行がないことが原因です。
Unix/Linuxの世界では、テキストファイルの末尾に常に空の行を付けるのが慣例だと思います。

私がそれをテストしている間に私が面白いと思った他のいくつかのこと:

  • このコマンドは、cygwinでは動作が異なります。
  • grep home american.txt | sort| uniq -uは問題なく動作します。
1
David Dai

David Daicas によって疑われるように、2つの行は実際には異なりますが、唯一の違いは非表示の文字にあります。

ファイルはWindowsテキストファイルです。 Windowsテキストファイルでは、行は2文字のシーケンスCR LF(キャリッジリターン、ラインフィード)で区切られます。 Unixテキストファイルでは、行はLF(改行、改行とも呼ばれます)文字で終了します。 cat -Aは、CRを^Mとして示し、改行を$として示し、その後に改行が続きます。

WindowsテキストファイルがUnixユーティリティによって処理されると、Unixユーティリティはすべての行の終わりに余分なCR文字を認識します。 Unixユーティリティに関する限り、CRは単なる普通の文字です。末尾にCRがある行は、末尾にCRがないことを除いて同じ行とは異なります。さらに、Windowsでは、改行シーケンスは区切り文字であるため、ファイルの最後にCR、LFはありません。ただし、Unixでは、テキストファイルは、空でない限り、常にLF文字で終わります。したがって、Unixユーティリティを使用してWindowsテキストファイルを処理すると、Unixユーティリティに表示されるのは、すべての行の終わりにCRが付いたファイル(CR文字は改行のUnixエンコーディングの一部ではないため)といくつかの末尾のテキストです。これは行の一部ではありません(最後に改行がないため)。

Unixテキストユーティリティは、最後の改行がないために入力が有効なテキストファイルでない場合の動作が異なります。 GNUユーティリティ(組み込みLinuxやCygwinにないもの)は、このようなファイルをテキストファイルとして扱い、最後の改行がないように努めます。 sortコマンドは行をシャッフルし、未完成の入力行を処理しますが、出力の最後に常に改行を出力します。したがって、sortコマンドでは、CRで終わらない最後の入力行を除いて、それぞれが文字CRで終わる一連の行のように見えます。出力では、最後の入力行に対応する1行を除いて、すべての行がCRで終わります。

uniqは、brave!とCRで終わる行の束を確認し、そのうちの1つだけを保持します。また、brave!で終わる1つの行が表示されますが、CRは表示されません。この行は他のすべての行と異なるため、忠実に発行されます。

端末に出力を印刷すると、CR文字が端末にカーソルを現在の行の先頭に移動するように指示します。 LF文字は、カーソルを次の行の先頭に移動するように端末に指示します。したがって、シーケンスLFとCR、LFは視覚的に区別できず、2つの同じように見える線が表示されます。コマンドcat -Aは、印刷可能な文字を追加して区別します。

brave!で終わる行の1つにはキャリッジリターン(^M)があり、もう1つにはありません。 uniqは正しいです、それらは異なります。

最後の行を除くファイル内のすべての行には、キャリッジリターンがあります。 MS-DOSまたはWindowsのテキストエディタ(改行のみまたは\ nの代わりにCR/LFを行末に使用する)によって作成されたため、これらがあります。ファイルの最後の行にはCRまたはLF)がありません(そうでない場合は、その下に空白行があります)。

そのため、たとえば、tail -1 american.txtを実行すると、改行なしでテキストと同じ行に次のシェルプロンプトが表示されます。

1
cas