Differenza di spazio tra due file su Linux


15

Ho due file che, confrontando con diff, mostrano che ogni riga è cambiata. Quando li confronto con diff -w(ignorando gli spazi bianchi) mostra i pochi cambiamenti minimi che mi aspetto.

Ovviamente c'è una differenza tra gli spazi bianchi in ogni file, ma non so cosa siano o come trovarli. Ho provato a modificare i file per assicurarmi che lo spazio bianco sia in realtà uno spazio (al contrario delle schede) ma non sono sicuro di cos'altro fare.

Ho usato vim con :set list onper confermare che non c'era spazio finale alla fine delle linee.

Credo anche che ogni file abbia terminatori di linea Linux poiché vim non mostrava ^Mla fine delle righe.


1
Hai controllato gli spazi bianchi finali (alla fine di una riga)? Tale spazio verrà rilevato da diffmolti editor, tuttavia, per impostazione predefinita, questo spazio non è visibile.
Giovanni 1024,

Buon consiglio Ho usato vim con ": set list on", questo mostrava "$" alla fine della riga e non c'era spazio finale. Aggiornerò la mia domanda
Romski

Se sei un vimutente, hai provato a usare vimdiff file1 file2per vedere quali sono le differenze?
Giovanni 1024,

@ John1024 Non ero a conoscenza di Vimdiff, ma sembra promettente. Aggiungilo come risposta e accetterò
Romski

1
Vim mostra ^ M solo quando rileva erroneamente una fine della linea Unix ma il file ha effettivamente la fine della linea DOS. Di solito questo accade se hai una linea mista che termina in un singolo file, ad esempio applicando una patch con una linea diversa dal file originale. Quando vim rileva che la riga DOS termina correttamente, non avrebbe mostrato ^ M.
Sdraiati Ryan il

Risposte:


7

Per gli vimutenti, è disponibile una comoda utility per mostrare le differenze esatte tra i file:

vimdiff file1 file2

Questo metterà ogni file in Windows, fianco a fianco e le differenze con evidenziate a colori.

Alcuni comandi utili quando in vimdiff

Mentre vimdiffsei dentro , alcuni comandi utili sono:

  • ]c: passa al prossimo cambio

  • [c: passa alla modifica precedente

  • ctrl-W ctrl-W: passa a un'altra finestra

  • zo: pieghe aperte

  • zc: pieghe ravvicinate

Esempio

Ecco un esempio di vimdiffin un xtermconfronto di due versioni di un cupsfile di configurazione:

inserisci qui la descrizione dell'immagine

Puoi vedere che lunghe sezioni di linee identiche sono state compresse. Possono essere riaperti con zo.

La combinazione di colori varia in base alle impostazioni dell'opzione. Nell'esempio sopra, quando una linea appare in un file ma non nell'altro, a quella linea viene assegnato uno sfondo blu scuro. Nell'altro file, le linee mancanti sono indicate da linee tratteggiate. Quando una linea appare in entrambi i file ma presenta alcune differenze, le parti invariate delle linee hanno uno sfondo rosa e le parti modificate hanno uno sfondo rosso.


14

Su FreeBSD o sulla maggior parte dei sistemi Linux, puoi inviare l'output di diff through cat -v -e -tper mostrare le differenze di spazio.

diff file1 file2 | cat -vet

Le schede verranno visualizzate come ^I, a $verrà visualizzato alla fine di ogni riga in modo da poter vedere spazi vuoti finali e i caratteri non stampabili verranno visualizzati come ^Xo M-X.

Se si hanno coreutils GNU (disponibili sulla maggior parte delle distribuzioni Linux non occupate), è possibile semplificare questo

diff file1 file2 | cat -A

Sui sistemi busybox, utilizzare catv -vet.


2

Uno dei file è stato modificato su un computer Windows?

La terminazione di linea standard su Windows è CRLF, dove su Linux è semplicemente LF (e su Mac era CR, ma sospetto che sia cambiato da OS X).

Prova wc -li file e vedi quante righe, quindi vedi se la differenza di dimensione è uguale al numero di righe (l'ultima riga potrebbe non essere terminata in un file).


Grazie per la risposta rapida. Fare un conteggio di riga mostra che un file ha 5 righe in più (mi aspetto che abbia apportato modifiche). Ho ricevuto un file da una macchina Linux e l'altro è stato estratto da un repository di codice su Linux. Credo che la visualizzazione di un file con terminatori di Windows in vim mostrerà l'ultimo carattere come ^ M e non è così.
Romski,

3
vim è effettivamente abbastanza intelligente da rilevare automaticamente la terminazione della linea, vedere stackoverflow.com/questions/3852868 per i dettagli.
fencepost

Non ero conscio di ciò! Ricontrollerò
Romski il

2

odposso aiutare. Il comando Dump ottale può mostrare i contenuti in esadecimali. Questo può aiutarti a vedere quali byte, inclusi byte nulli o spazi bianchi imprevisti, si trovano in un file. Le possibili cause comuni possono essere LF vs CRLF, tabs vs space o ASCII vs Unicode (che spesso può avere un byte null prima di ogni byte normalmente visibile). od -x filenamedovrebbe rivelare uno di questi schemi. Se vuoi un modo più elaborato per visualizzare il file, qualsiasi "editor esadecimale" può fare bene. La cosa bella odè che, come il cutcomando, è integrato in molti sistemi Unix. Quindi, spesso, non è necessaria alcuna installazione separata.

Se hai bisogno di file più simili, trpuoi apportare alcune modifiche e sedfare di più. Probabilmente vorrei iniziare ls -lper vedere quale file è più grande, quindi visualizzare i byte per vedere cosa deve essere modificato, quindi cambiare uno dei file in modo che appaiano più simili.


1

Per scoprire dove sono i veri spazi bianchi e le schede puoi sostituirli usando sedad esempio:

$ cat file
  line 1
  line 2
    line 6
        line 7
$ sed 's/ /-/g; s/\t/<tab>/g' file
--line-1
--line-2
<tab>line-6
<tab><tab>line-7

E ora confronta i due file.


Ancora meglio, è possibile eseguire quel filtro sull'output diff. Oppure puoi utilizzare il filtro già pronto cat, come in superuser.com/a/913368/37154
clacke,

0

Il seguente contenuto è stato copiato qui dalla sezione "domanda" sopra, che è stata scritta da Romski.

Entrambi vimdiffe diff file1 file2 | cat -Asono stati molto utili dal punto di vista degli strumenti.

Infine, ho trovato un ulteriore problema. Alcuni dei miei file sono stati codificati con la distinta componenti UTF-8. Questo è stato evidenziato usando diff file1 file2 | cat -A. Questo si è manifestato M-oM-;M-?all'inizio del file interessato:

$ diff file1 file2 | cat -A
< package com.mycompany;$
---$
> M-oM-;M-?package com.mycompany;$

Mentre ci sono stati un certo numero di problemi, ho elencato un paio di comandi di seguito per coloro che hanno bisogno di ripulire i loro file:

# recursively remove UTF8 BOM
find . -type f -exec sed -i -e '1s/^\xEF\xBB\xBF//' {} \;

# recursively replace CRLF with LF
find . -type f -print0 | xargs -0 dos2unix
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.