Wie ein diff machen, wenn Zeilen woanders stehen?

Du hast Probleme mit Deinem eMail-Programm, Webbrowser oder Textprogramm? Dein Lieblingsprogramm streikt?
Antworten
dirk11
Beiträge: 2873
Registriert: 02.07.2013 11:47:01

Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von dirk11 » 08.02.2025 18:32:52

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?

tobo
Beiträge: 2523
Registriert: 10.12.2008 10:51:41

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von tobo » 08.02.2025 18:44:36

Hilft es dir, wenn du beide Dateien im Speicher zuerst sortierst?

Code: Alles auswählen

diff --side-by-side --suppress-common-lines <(sort bla.txt) <(sort blb.txt)
PS: Oder `comm' auf die Sortierung angewendet.

dirk11
Beiträge: 2873
Registriert: 02.07.2013 11:47:01

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von dirk11 » 08.02.2025 19:23:57

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!

tobo
Beiträge: 2523
Registriert: 10.12.2008 10:51:41

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von tobo » 08.02.2025 19:31:54

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)

uname
Beiträge: 12581
Registriert: 03.06.2008 09:33:02

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von uname » 08.02.2025 20:47:17

Kann das vielleicht Debiankdiff3? Ist aber ein KDE-Programm.

Oder online bei nicht vertraulichen Daten: https://www.diffchecker.com

dirk11
Beiträge: 2873
Registriert: 02.07.2013 11:47:01

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von dirk11 » 08.02.2025 22:50:32

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.

tobo
Beiträge: 2523
Registriert: 10.12.2008 10:51:41

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von tobo » 08.02.2025 23:18:48

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!?

uname
Beiträge: 12581
Registriert: 03.06.2008 09:33:02

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von uname » 09.02.2025 08:42:25

Mir fällt noch vimdiff ein. Keine Ahnung wie gut das ist.

chrbr
Beiträge: 637
Registriert: 29.10.2022 15:53:26

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von chrbr » 09.02.2025 23:42:08

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.

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/"
Die tags-Datei kann dann beliebig viele Einträge haben wir der folgende Auschnitt zeigt.

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./
Jetzt ist mir nur noch nicht klar, ob das überhaupt zu Deinem Problem passt.

UnixFan
Beiträge: 32
Registriert: 19.10.2023 13:50:46

Re: Wie ein diff machen, wenn Zeilen woanders stehen?

Beitrag von UnixFan » 21.02.2025 19:21:25

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.

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.
Viele Grüße
Jörg

Antworten