Wie ein diff machen, wenn Zeilen woanders stehen?
Wie ein diff machen, wenn Zeilen woanders stehen?
Hi Leute,
normalerweise vergleiche ich (Text-) Dateien (Config o.Ä.) mittels diff. Also diff -u bla.txt blb.txt oder diff -y bla.txt blb.txt
Jetzt habe ich aber das Problem, dass in zwei weitestgehend identischen Files Einträge stehen, die zwar in beiden vorhanden sind (und das sogar identisch), aber beispielsweise bei bla in Zeile 12 und bei blb erst in Zeile 71. Wie kriege ich das übereinander? Sprich, wie kann ich auf der Kommandozeile ein diff machen, welches auch das berücksichtigt und diese zwar gleichen, aber an unterschiedlichen Positionen stehenden Zeilen findet?
normalerweise vergleiche ich (Text-) Dateien (Config o.Ä.) mittels diff. Also diff -u bla.txt blb.txt oder diff -y bla.txt blb.txt
Jetzt habe ich aber das Problem, dass in zwei weitestgehend identischen Files Einträge stehen, die zwar in beiden vorhanden sind (und das sogar identisch), aber beispielsweise bei bla in Zeile 12 und bei blb erst in Zeile 71. Wie kriege ich das übereinander? Sprich, wie kann ich auf der Kommandozeile ein diff machen, welches auch das berücksichtigt und diese zwar gleichen, aber an unterschiedlichen Positionen stehenden Zeilen findet?
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Hilft es dir, wenn du beide Dateien im Speicher zuerst sortierst?
PS: Oder `comm' auf die Sortierung angewendet.
Code: Alles auswählen
diff --side-by-side --suppress-common-lines <(sort bla.txt) <(sort blb.txt)
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Mhmm. Das ergibt dann auf einmal nur noch sechs unterschiedliche Zeilen. Was mir nicht klar ist: Fehlende bzw. zu viele Zeilen (die ja auch "diff" sind) werden nicht unterschlagen?
Sonst würde ich nach einem ersten Test sagen, dass das funktioniert. Den Kommentar mit dem "comm" verstehe ich allerdings nicht.
EDIT: ich hab's mal mit -u gemacht, das macht es für mich deutlicher. Es scheint das zu machen, was ich brauche - danke!
Sonst würde ich nach einem ersten Test sagen, dass das funktioniert. Den Kommentar mit dem "comm" verstehe ich allerdings nicht.
EDIT: ich hab's mal mit -u gemacht, das macht es für mich deutlicher. Es scheint das zu machen, was ich brauche - danke!
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
comm ist ein eigenständiger Befehl und da könnte man sich die Optionen -1, -2 und/oder - 3 (auch in Kombination) ansehen. Z.B. so was:
Code: Alles auswählen
comm -3 <(sort bla.txt) <(sort blb.txt)
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Kann das vielleicht
kdiff3? Ist aber ein KDE-Programm.
Oder online bei nicht vertraulichen Daten: https://www.diffchecker.com

Oder online bei nicht vertraulichen Daten: https://www.diffchecker.com
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
OMG. Danke, aber mir kommen hier nicht noch Gigabyteweise KDE-Libs drauf. Bis KDE3 habe ich das nur benutzt, dann wurde es mir zu verspielt, ich bin dann über Gnome2 bis jetzt bei xfce gelandet. Und online diffen ist natürlich auch keine Lösung, jedenfalls nicht dauerhaft. Aber wie gesagt, das o.g. funktioniert.
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Unabhängig davon, ob es vorher funktionierte, macht es vermutlich generell wenig Sinn, ein diff durch ein anderes diff zu ersetzen, selbst wenn das neue diff online zugänglich ist!?
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Mir fällt noch vimdiff ein. Keine Ahnung wie gut das ist.
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Hallo Dirk,
weisst Du denn (in etwa), wonach Du suchst? Bei Übersetzungen habe ich oft das Problem, dass in Vorlagen einer Programmfamilie immer ähnliche Formulierungen verwendet werden, die dann aber doch im Detail unterschiedlich sind. Ich bin inzwischen dazu übergegangen, mir für vim eine tags-Datei erstellen zu lassen, wie sie auch das Programm ctags erzeugt. Im ursprünglichen ctags kann man damit zum Beispiel von Stellen, in denen Funktionen verwendet werden zur eigentlichen Definition der Funktionen springen.
Im folgenden Beispiel würde mir vim bei der Suche nach dem tag "input image" die zwei Stellen als Sprungziel anbieten.
Die tags-Datei kann dann beliebig viele Einträge haben wir der folgende Auschnitt zeigt.
Jetzt ist mir nur noch nicht klar, ob das überhaupt zu Deinem Problem passt.
weisst Du denn (in etwa), wonach Du suchst? Bei Übersetzungen habe ich oft das Problem, dass in Vorlagen einer Programmfamilie immer ähnliche Formulierungen verwendet werden, die dann aber doch im Detail unterschiedlich sind. Ich bin inzwischen dazu übergegangen, mir für vim eine tags-Datei erstellen zu lassen, wie sie auch das Programm ctags erzeugt. Im ursprünglichen ctags kann man damit zum Beispiel von Stellen, in denen Funktionen verwendet werden zur eigentlichen Definition der Funktionen springen.
Im folgenden Beispiel würde mir vim bei der Suche nach dem tag "input image" die zwei Stellen als Sprungziel anbieten.
Code: Alles auswählen
#!/bin/sh
# Erzeuge eine Ergänzung für eine tags-Datei.
#
# find ./ -name "*.po" -exec grep -H "input image" {} \;
# ergibt Zeilen der Art
# ./pamrestack.1.po:"the number of pixels in the input image."
# ./pamundice.1.po:msgid "There must not be any input image narrower than this."
# Daraus muss werden
# input image pamrestack.1.po /the number of pixels in the input image./
# input image pamundice.1.po /There must not be any input image narrower than this./
find ./ -name "*.po" -exec grep -H "$1" {} \;\
|sed -e 's/\.po\:[msgid\ ]*\"/\.po\t\//'\
|sed -e 's/\"$/\//'\
|sed -e "s/^\.\//$1\t/"
Code: Alles auswählen
unique abbreviation pamdice.1.po /You can use the minimum unique abbreviation of the options. You can use two /
unique abbreviation pnmcrop.1.po /Minimum unique abbreviation of option is acceptable. You may use double /
unique abbreviation pamcut.1.po /Minimum unique abbreviations of option are acceptable. You may use double /
unique abbreviation pamrestack.1.po /Minimum unique abbreviations of option are acceptable. You may use double /
unique abbreviation pamundice.1.po /You can use the minimum unique abbreviation of the options. You can use two /
unique abbreviation pamshuffle.1.po /Minimum unique abbreviations of option are acceptable. You may use double /
image as output pbmtoascii.1.po /graphic image as output./
image as output xwdtopnm.1.po /image as output. The type of the output image depends on the input file - /
image as output pnmcrop.1.po /the background color, and produces the same type of image as output./
image as output pamcut.1.po /specified rectangle, and produces the same kind of image as output./
Re: Wie ein diff machen, wenn Zeilen woanders stehen?
Tut mir leid, dass ich diesen Thread jetzt erst sehe.
Vor langen Jahren habe ich mir mal das folgende Skript geschrieben. Damals ging es vermutlich darum, lange make-Protokolle zu vergleichen, in denen jeweils mehrere Compiler parallel gelaufen waren und dadurch die Meldungen zu einzelnen Files in verschiedener Reihenfolge standen.
Viele Grüße
Jörg
Vor langen Jahren habe ich mir mal das folgende Skript geschrieben. Damals ging es vermutlich darum, lange make-Protokolle zu vergleichen, in denen jeweils mehrere Compiler parallel gelaufen waren und dadurch die Meldungen zu einzelnen Files in verschiedener Reihenfolge standen.
Code: Alles auswählen
#! /bin/sh
#
# minimize_diffs Repeatedly apply "diff" to two files whose contents
# may differ mostly in sequence,
# like protocols of parallel "make" runs
#
# $1, $2 the two files to compare
# (not checked for existence as files, to include '-' for
# anonymous pipes as well as named pipes)
#
# 2009-Mar-04 J.Bruehe Allow "$DIFF" to override (default) "diff"
# 2004-Aug-09 J.Bruehe Minor change: Put date and line count on one line
# 2004-Aug-06 J.Bruehe Initial version
#
# The principle on which this script works is described at the end!
if [ -n "$DIFF" ]
then
echo "Using '$DIFF'"
else
DIFF=diff
fi
$DIFF $1 $2 > file_diff
NL_OLD=1999999 # just a huge number
NL_NEW=`wc -l < file_diff`
date
wc file_diff
while [ "$NL_NEW" -gt 0 -a "$NL_NEW" -lt "$NL_OLD" ]
do
NL_OLD=$NL_NEW
grep '^< ' file_diff | cut -c3- > file_left
grep '^> ' file_diff | cut -c3- > file_right
$DIFF file_left file_right > file_diff
NL_NEW=`wc -l < file_diff`
echo `date` `wc file_diff`
done
# This tool was written to compare files with reordered lines.
# In general, they are of the form:
# A D
# x y
# y x
# B E
# A simple 'diff' may recognize the identical 'x' lines and produce
# (a '_' stands for some line number):
# _,_c_,_
# < A
# ---
# > D
# > y
# _,_c_,_
# < y
# < B
# ---
# > E
# Now, the script extracts the lines marked '< ' and '> ' into temporary files:
# A D
# y y
# B E
# The next 'diff' will now produce:
# _,_c_,_
# < A
# ---
# > D
# _,_c_,_
# < B
# ---
# > E
# Assuming that the parts A, B, D, and E contain still more identical lines,
# this process is repaeted as long as the size of the 'diff' output shrinks.
#
# Note that in the process of reduction, the order of the lines does not change,
# so all lines of one input file that do not have a match in the other file
# will remain in their original sequence. However, all line number information
# is lost, so from the output you cannot tell whether the non-matching line
# comes from the beginning, the end, or some middle part of the input file.
Jörg