追加された行と削除された行のみを表示するようにdiffを取得するにはどうすればよいですか? diffがそれを実行できない場合、どのツールを使用できますか?
それを見る別の方法:
ファイルaにのみ存在する行を表示:(つまり、aから削除されたもの)
comm -23 a b
ファイルbにのみ存在する行を表示:(つまり、bに追加されたもの)
comm -13 a b
どちらか一方のファイルにのみ存在する行を表示:(両方ではない)
comm -3 a b | sed 's/^\t//'
(警告:ファイルa
にTABで始まる行がある場合、そのファイル(最初のTAB)は出力から削除されます。)
注:comm
が正しく機能するには、両方のファイルをソートする必要があります。それらがまだソートされていない場合は、ソートする必要があります。
sort <a >a.sorted
sort <b >b.sorted
comm -12 a.sorted b.sorted
ファイルが非常に長い場合、追加のコピーが必要になるため、ディスク容量が2倍になるため、これはかなりの負担になる可能性があります。
comm
はあなたが望むことをするかもしれません。そのmanページから:
説明
ソートされたファイルFILE1とFILE2を行ごとに比較します。
オプションなしで、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
Manページにあるように、ファイルは事前にソートする必要があります。
コンテキストなしで追加と削除を表示するには、行番号+、-、<、>!など、次のように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
これがdiffがデフォルトで行うことです...おそらく、空白を無視するためにいくつかのフラグを追加する必要がありますか?
diff -b -B
空白行と異なる数のスペースは無視する必要があります。
いいえ、実際にdiff
は、2つのファイルの違いを実際の人が考えているように示しているわけではありません。あるファイルを別のファイルに変更するために使用するpatch
などのツールの一連の編集コマンドを生成します。
探していることを実行しようとする試みの難しさは、削除された行に続いて追加された行に対して、変更された行を構成するものを定義する方法です。また、線が隣接して追加、削除、および変更されたときに何をすべきか。
視覚的な比較ツールは2つのファイルを合わせて、行数は同じで内容が異なるセグメントが変更されたセグメントと見なされるようにします。一致するセグメント間の完全に新しい行は、追加されたセグメントと見なされます。
これはsdiffコマンドラインツールの動作方法でもあり、ターミナルで2つのファイルを並べて比較します。変更された行は|で区切られますキャラクター。行がファイルAにのみ存在する場合、<が区切り文字として使用されます。行がファイルBにのみ存在する場合、区切り文字として>が使用されます。ファイルに<と>の文字がない場合は、これを使用して、追加された行のみを表示できます。
sdiff A B | grep '[<>]'
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}'
私はこの特定のフォームがしばしば役立つと思います:
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
[...]
Ubuntu 18.04でテスト済み。