追加および削除された行のみを表示するためにdiffを取得するにはどうすればよいですか?diffでできない場合、どのツールができますか?


69

追加および削除された行のみを表示するためにdiffを取得するにはどうすればよいですか?diffでできない場合、どのツールができますか?


2
追加と削除の意味をより明確に定義する必要があります。具体的には、行を変更できますか?その場合、変更された行をどのように処理しますか?厳密に行指向のチェックを行う場合、行の変更は、削除される古い行と追加される新しい行と同じです。たとえば、2つに分割された行をどのように処理する必要がありますか?2つの1行が変更されたのですか?2行変更されましたか?1行削除して2行追加しましたか?行が決して変更されず、単に追加および削除されることを保証できない限り、より良い定義なしでは失敗する運命にあると思います。
クリストファーキャシェル

質問は非常に不明瞭です。しかし、質問の少なくとも1つの解釈に答えることができますdiff A B | grep '^[<>]'
カスペルド

探してcommいるかもしれません。
ジェニーD 14

@ChristopherCashell、彼はソート順を無視することを意味します。一般的な一般的な問題。通常、これは通常の差分を行う前に、まず各側のセグメント(行)をソートすることによって行われます。
Pacerier

@Pacerier、あなたはそれについて確かですか?それとも推測していますか?質問では、並べ替えや検索順序については言及も示唆もされていません。現状では、質問は明確ではなく、さまざまな方法で解釈できます。彼が何を求めているのかを確実に知ることなく、私たちは仮定を行い、実際の問題を解決する場合としない場合の解決策を提供しています。さらに、回答の1つに対する元のポスターのコメントは、これがソートに関連していないことを示唆してます。「追加および削除」対「変更」の意味に関係しています。
クリストファーキャシェル16年

回答:


82

通信をお試しください

別の見方:

  • ファイルaにのみ存在する行を表示します:(つまり、aから削除されたもの)

    comm -23 a b
    
  • ファイルbにのみ存在する行を表示します:(つまり、bに追加されたもの)

    comm -13 a b
    
  • どちらかのファイルにのみ存在する行を表示します:(両方ではありません)

    comm -3 a b | sed 's/^\t//'
    

(警告:ファイルにaTABで始まる行がある場合、そのファイル(最初のTAB)は出力から削除されます。)

ソートされたファイルのみ

注:両方のファイルをcomm適切に機能させるには、ソートする必要があります。それらがまだソートされていない場合は、ソートする必要があります。

sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted

ファイルが非常に長い場合、追加のコピーが必要になるため、ディスク容量が2倍になるため、これはかなりの負担になる可能性があります。


5
ただ、正しい結果を生成する(大文字と小文字を区別)このソリューションに両方のファイルをソートする必要があることを追加したい
marmor

1
最新の十分なシェルでは、次のようにインラインで並べ替えることができますcomm -12 <(sort a) <(sort b)
ジョシュア

14

commあなたがしたいことをするかもしれません。そのmanページから:

記述

ソートされたファイルFILE1とFILE2を1行ずつ比較します。

オプションなしで、3列の出力を生成します。列1にはFILE1に固有の行が含まれ、列2にはFILE2に固有の行が含まれ、列3には両方のファイルに共通の行が含まれます。

これらの列は、それぞれと-1で抑制できます。-2-3

例:

[root@dev ~]# cat a
common
shared
unique

[root@dev ~]# cat b
common
individual
shared

[root@dev ~]# comm -3 a b
    individual
unique

そして、もしあなたがただユニークな行が欲しいなら、それらがどのファイルにあるか気にしないなら:

[root@dev ~]# comm -3 a b | sed 's/^\t//'
individual
unique

マニュアルページにあるように、ファイルは事前にソートする必要があります。


9

コンテキスト、行番号、+、-、<、>なしで追加と削除を表示するには など、次のようにdiffを使用できます。

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

たとえば、2つのファイルがある場合:

a.txt

Common
Common
A-ONLY
Common

b.txt

Common
B-ONLY
Common
Common

次のコマンドは、aから削除された行またはbに追加された行を表示します。

diff --changed-group-format='%<%>' --unchanged-group-format='' a.txt b.txt 

出力:

B-ONLY
A-ONLY

このわずかに異なるコマンドは、a.txtから削除された行を表示します。

diff --changed-group-format='%<' --unchanged-group-format='' a.txt b.txt 

出力:

A-ONLY

最後に、このコマンドはa.txtに追加された行を表示します

diff --changed-group-format='%>' --unchanged-group-format='' a.txt b.txt 

出力

B-ONLY

2

それはデフォルトでdiffが行うことです...たぶん、空白を無視するためにいくつかのフラグを追加する必要がありますか?

diff -b -B

空白行と異なる数のスペースを無視する必要があります。


1
いいえ、変更された行(文字または4つの異なる行)も表示されます。左または右にのみ存在する行が必要です。
C.ロス

2
CHANGEDファイルの異なるバージョンはそれぞれ左または右にのみ存在すると主張できます。
マークドレイトン

2
diff(または他のツール)が何が変更され、何が削除された行が新しい行に置き換えられているかを確実に知る方法はありません。
シアン

1
技術的には、diffは「変更された」行を、元の行が削除され、新しい行が追加されたものとして扱います。したがって、技術的には、追加および削除された行のみを表示します。
KFro

2

いいえ、diff実際に2つのファイルの違いを考えられるように表示しません。patchあるファイルを別のファイルに変更するために使用するようなツールの一連の編集コマンドを生成します。

あなたが探していることをしようとする試みの難しさは、変更された行と削除された行の後に追加された行を構成するものをどのように定義するかです。また、行が互いに隣接して追加、削除、および変更された場合の対処方法。


私の考えは正確に。元の文字を変更するのではなく、新しい文字と見なすために、行の何パーセントの文字を変更する必要がありますか?技術的には、1つの文字が共通していても、削除や挿入ではなく「変更」と見なすことができます。
カミルKisiel

1
diffソースを確認してから長い時間が経ちましたが、同期を保つために2つのファイルが一致する場所を追跡するために、あらゆる種類の回転を覚えているようです。行があります。しかし、(オプションで)折りたたまれた空白または大文字と小文字の区別を除いて、行内一致を覚えていません。または(おそらく)その影響を与える言葉。いずれにせよ、それはすべてでpatchあり、「vgrep」はただ乗って来ます。多分。火曜日に。
デニスウィリアムソン

2

視覚比較ツールは2つのファイルをまとめて、同じ行数で異なるコンテンツを持つセグメントが変更されたセグメントと見なされるようにします。一致するセグメント間の完全に新しい行は、追加されたセグメントと見なされます。

これは、sdiffコマンドラインツールの動作方法でもあり、ターミナル内の2つのファイルの比較を並べて表示します。変更された行は|で区切られます キャラクター。ファイルAのみに行が存在する場合、区切り文字として<が使用されます。ファイルBにのみ行が存在する場合、>が区切り文字として使用されます。ファイルに<と>の文字がない場合、これを使用して追加された行のみを表示できます。

sdiff A B | grep '[<>]'

2

senarviのおかげで、あなたの解決策(投票されていない)は実際に、何トンものページで年齢を探した後、私が望んでいたものを正確にくれました。

あなたの答えを使用して、変更/追加/削除されたもののリストを取得するために私が思いついたものを以下に示します。この例では、2つのバージョンの/ etc / passwdファイルを使用し、関連レコードのユーザー名を出力します。

#!/bin/bash
sdiff passwd1 passwd2 | grep '[|]' | awk -F: '{print "changed: " $1}'
sdiff passwd1 passwd2 | grep '[<]' | awk -F: '{print "deleted: " $1}'
sdiff passwd1 passwd2 | grep '[>]' | awk -F\> '{print $2}' | awk -F: '{print "added: " $1}'

「行が変更された」と「行が削除され、その下または上に別の行が追加された」との違いはセマンティックであることに注意してください。一般的なテキストベースの差分ツールでは、これらのケースを区別できません。その結果、sdiffベースの回答はすべてのケースで確実に機能するわけではありません。
ミッコランタライネン

0

私はこの特定のフォームがしばしば役に立つと思います:

diff --changed-group-format='-%<+%>' --unchanged-group-format='' f g

例:

printf 'a\nb\nc\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

出力:

-b
-c
+B
+C
-e
-f
+E
+F

したがって、古い行が表示-され、直後に対応する新しい行が続き+ます。

の削除があった場合C

printf 'a\nb\nd\ne\nf\ng\n' > f
printf 'a\nB\nC\nd\nE\nF\ng\n' > g
diff --old-line-format=$'-%l\n' \
     --new-line-format=$'+%l\n' \
     --unchanged-line-format='' \
     f g

次のようになります。

-b
+B
+C
-e
-f
+E
+F

形式は次の場所で文書化されていman diffます。

       --line-format=LFMT
              format all input lines with LFMT`

そして:

       LTYPE is 'old', 'new', or 'unchanged'.
              GTYPE is LTYPE or 'changed'.

そして:

              LFMT (only) may contain:

       %L     contents of line

       %l     contents of line, excluding any trailing newline

       [...]

関連する質問:https : //stackoverflow.com/questions/15384818/how-to-get-the-difference-only-additions-between-two-files-in-linux

Ubuntu 18.04でテスト済み。


-1

File1:

text670_1
text067_1
text067_2

File2:

text04_1
text04_2
text05_1
text05_2
text067_1
text067_2
text1000_1

つかいます:

diff -y file1 file2

これは、repectivesファイルの2つの列を示しています。

出力:

text670_1                           
                                  > text04_1
                                  > text04_2
                                  > text05_1
                                  > text05_2
text067_1                           text67_1
text067_2                           text67_2
                                  > text1000_1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.