2009-04-21 5 views
17

Ho un file di configurazione che considero la mia configurazione di "base". Mi piacerebbe confrontare fino a 10 altri file di configurazione con quel singolo file di base. Sto cercando un rapporto in cui ogni file viene confrontato con il file di base.Come si "diff" più file su un singolo file di base?

Ho guardato diff e sdiff, ma non offrono completamente quello che sto cercando.

Ho considerato diff'ing la base contro ogni file singolarmente, ma il mio problema diventa quindi unendoli in un report. Idealmente, se manca la stessa linea in tutti i 10 file di configurazione (rispetto alla configurazione di base), mi piacerebbe che fosse riportato in modo facile da visualizzare. Ad esempio, qui è in sostanza quello che sto cercando di essere in grado di farlo (questo esempio ha 1 file di base e 3 file di configurazione ciascuno individualmente confrontato con il config di base):

Here's a link to the picture below alt text http://img141.imageshack.us/img141/3264/config2.png

noti che alcune righe mancano in molti dei file di configurazione (se confrontati individualmente con la base). Mi piacerebbe essere in grado di mettere quelli sulla stessa linea (come sopra).

nota, schermata sopra è semplicemente un mockup, e non un effettiva applicazione.

Ho guardato usando alcuni controlli Delphi per questo e scrivendo il mio (ho Delphi 2007), ma se c'è un programma che già lo fa, lo preferirei.

I controlli Delphi che ho visto sono TDiff e TrmDiff* components included in rmcontrols.

+0

Ho messo insieme una soluzione realizzabile. Essenzialmente ho scritto la mia app Delphi che esegue una porta Windows di sdiff.exe contro il 1 ° e il 2 ° file. Quindi il 1 ° e il 3 ° file. Poi il 1 ° e il 4 °, ecc. Quindi compilo un dbgrid con questi risultati (come nello screenshot). Poi metto in risalto. È lento (perché è a thread singolo) e brutto. Ma fa principalmente quello che voglio. E non sto lavorando con molti dati – Mick

risposta

10

Per le persone che sono ancora chiedendo come fare questo, diffuse è la risposta più vicina, lo fa N-way merge da modo di visualizzare tutti i file e di fare tre vie di unione tra neighboors.

+0

Ed è in Debian e Ubuntu repository di pacchetti. Installa con apt-get install diffuse. Un altro aspetto interessante è che se i tuoi file hanno nomi che seguono uno schema (o vuoi tutti i file in una cartella) puoi usare un asterisco con tutti i caratteri con "diffuse partname * .ext" – mlncn

0

Si potrebbe voler esaminare alcuni componenti Merge come quello che si descrive è esattamente ciò che gli strumenti di unione fanno tra la base comune, il file di controllo della versione e il file locale. Tranne che vuoi più di 2 file (+ base) ...
Solo il mio $ 0.02

1

Prova software del motorino Beyond Compare. Supporta l'unione a 3 vie ed è scritto in Delphi/Kylix per il supporto multipiattaforma. L'ho usato abbastanza estesamente (anche su una VPN) e ha funzionato bene.

1

per f in file1 file2 file3 file4 file5; fai echo "$ f \ n \ n" >> outF; diff $ f baseFile >> outF; echo "\ n \ n" >> outF; fatto

+0

Questo è molto semplice e dà un output che puoi passare in giro (ho trovato utile usare diff -u e passarlo a enscript -2Gr -Ediff) –

1

Diff3 dovrebbe aiutare. Se sei su Windows, puoi usarlo da Cygwin o da diffutils.

1

Ho creato il mio strumento diff DirDiff perché non volevo le parti che corrispondono due volte sullo schermo e le diverse parti sopra l'altra per un facile confronto. È possibile utilizzarlo in modalità directory su una directory con un numero uguale di copie del file di base. Non esegue il rendering delle esportazioni di diff, ma lo sono list it as a feature request.

4

Nessuno degli strumenti diff/merge esistenti farà ciò che si desidera. In base allo screenshot di esempio, stai cercando un algoritmo che esegua allineamenti su più file e fornisca pesi appropriati in base alla somiglianza di linea.

Il primo numero pesando l'allineamento basato su linea somiglianza.Gli algoritmi di allineamento più popolari, compreso quello usato da GNU diff, TDiff e TrmDiff, eseguono un allineamento basato sugli hash delle linee e controllano solo se le linee corrispondono esattamente o meno. Puoi pre-elaborare le linee per rimuovere gli spazi bianchi o modificare tutto in lettere minuscole, ma il gioco è fatto. Aggiungi, rimuovi o cambia una lettera e gli elementi di allineamento dell'intera linea sono diversi. Qualsiasi allineamento di linee diverse a quel punto è puramente casuale.

Beyond Compare tiene conto della similarità di linea, ma funziona davvero solo per i confronti a 2 vie. Confronta! ha anche una sorta di algoritmo di similarità, ma è anche limitato ai confronti a 2 vie. Può rallentare notevolmente il confronto e non sono a conoscenza di nessun altro componente o programma, commerciale o open source, che nemmeno ci provi.

L'altro problema è che si desidera anche un confronto a più file. Ciò significa eseguire l'algoritmo diff due volte un sacco di volte e unire i risultati insieme o trovare un algoritmo che faccia più allineamenti contemporaneamente.

cucitura sarà difficile: il campione mostra che il file originale può avere linee mancanti, così avresti bisogno di confrontare tutti i file a tutti gli altri file per ottenere il un mucchio di allineamenti, e poi avresti bisogno di lavorare il modo migliore per abbinare questi allineamenti. Un algoritmo ingenuo di cucitura è abbastanza facile da fare, ma sarà incasinato da partite banali (ad esempio righe vuote).

Esistono documenti di ricerca che coprono l'allineamento di più sequenze contemporaneamente, ma di solito sono incentrate sui confronti del DNA, dovresti sicuramente codificarlo da solo. Wikipedia copre molte delle nozioni di base, quindi probabilmente avresti bisogno di passare a Google Scholar.

0

So che questo è un vecchio thread, ma vimdiff lo fa (quasi) esattamente quello che stai cercando con l'ulteriore vantaggio di essere in grado di modificare i file direttamente dalla prospettiva diff.

0

Ma nessuna delle soluzioni ha ancora più di 3 file. Quello che ho fatto è stato più disordinato, ma per lo stesso scopo (confrontando contenuto di più file di configurazione, nessun limite tranne variabili di memoria e bash)

While per leggere un file in un array:

loadsauce() { 
index=0 
while read SRCCNT[$index] 
do let index=index+1 
done < $SRC 
} 

Anche in questo caso per il file di destinazione

loadtarget() { 
index=0 
while read TRGCNT[$index] 
do let index=index+1 
done < $TRG 
} 

confronto tra stringhe

brutediff() { 
# Brute force string compare, probably duplicates diff 
# This is very ugly but it will compare every line in SRC against every line in TRG 
# Grep might to better, version included for completeness 
for selement in $(seq 0 $((${#SRCCNT[@]} - 1))) 
do for telement in $(seq 0 $((${#TRGCNT[@]} - 1))) 
    do [[ "$selement" == "$telement" ]] && echo "${selement} is in ${SRC} and ${TRG}" >> $OUTMATCH 
    done 
done 
} 

e, infine, un ciclo per farlo con un elenco di file

for sauces in $(cat $SRCLIST) 
do echo "Checking ${sauces}..." 
    loadsauce 
    loadtarget 
    brutediff 
    echo -n "Done, " 
done 

E 'ancora testato/buggy e incompleta (come l'ordinamento i duplicati o la compilazione di una lista per ogni riga con file comuni,) ma è sicuramente una mossa la direzione che l'OP stava chiedendo. Penso che Perl sarebbe meglio per questo però.