Esistono due file chiamati "a.txt" e "b.txt" hanno entrambi un elenco di parole. Ora voglio controllare quali parole sono extra in "a.txt" e non in "b.txt" .
Ho bisogno di un algoritmo efficiente in quanto ho bisogno di confrontare due dizionari.
Esistono due file chiamati "a.txt" e "b.txt" hanno entrambi un elenco di parole. Ora voglio controllare quali parole sono extra in "a.txt" e non in "b.txt" .
Ho bisogno di un algoritmo efficiente in quanto ho bisogno di confrontare due dizionari.
Risposte:
se hai installato vim, prova questo:
vimdiff file1 file2
o
vim -d file1 file2
lo troverai fantastico.
Ordinali e usa comm
:
comm -23 <(sort a.txt) <(sort b.txt)
comm
confronta i file di input (ordinati) e, per impostazione predefinita, genera tre colonne: righe univoche per a, righe univoche per b e righe presenti in entrambi. Specificando -1
, -2
e / o -3
è possibile sopprimere l'output corrispondente. Pertanto comm -23 a b
elenca solo le voci che sono uniche per a. Uso la <(...)
sintassi per ordinare i file al volo, se sono già ordinati non è necessario.
comm
è più efficiente perché esegue il lavoro in una sola esecuzione, senza memorizzare l'intero file in memoria. Dal momento che stai usando dizionari che molto probabilmente sono già ordinati, non hai nemmeno bisogno di sort
loro. L'uso grep -f file1 file2
d'altro canto caricherà l'intero file1
in memoria e confronterà ogni riga file2
con tutte quelle voci, il che è molto meno efficiente. È utile soprattutto per piccoli, non ordinati-f file1
.
\n
sarà incluso anche per fare il confronto.
È possibile utilizzare lo diff
strumento in Linux per confrontare due file. È possibile utilizzare le opzioni --changed-group-format e --unchanged-group-format per filtrare i dati richiesti.
Le seguenti tre opzioni possono essere utilizzate per selezionare il gruppo pertinente per ciascuna opzione:
'% <' ottiene linee da FILE1
'%>' ottiene linee da FILE2
'' (stringa vuota) per rimuovere le righe da entrambi i file.
Ad esempio: diff --changed-group-format = "% <" --unchanged-group-format = "" file1.txt file2.txt
[root@vmoracle11 tmp]# cat file1.txt
test one
test two
test three
test four
test eight
[root@vmoracle11 tmp]# cat file2.txt
test one
test three
test nine
[root@vmoracle11 tmp]# diff --changed-group-format='%<' --unchanged-group-format='' file1.txt file2.txt
test two
test four
test eight
Se preferisci lo stile di output diff git diff
, puoi usarlo con il --no-index
flag per confrontare i file che non sono in un repository git:
git diff --no-index a.txt b.txt
Usando un paio di file con circa 200k stringhe di nomi di file in ciascuno, ho confrontato (con il time
comando integrato ) questo approccio rispetto ad alcune delle altre risposte qui:
git diff --no-index a.txt b.txt
# ~1.2s
comm -23 <(sort a.txt) <(sort b.txt)
# ~0.2s
diff a.txt b.txt
# ~2.6s
sdiff a.txt b.txt
# ~2.7s
vimdiff a.txt b.txt
# ~3.2s
comm
sembra essere di gran lunga il più veloce, mentre git diff --no-index
sembra essere l'approccio più veloce per l'output in stile diff.
Aggiornamento 25-03-2018 È possibile omettere il --no-index
flag a meno che non ci si trovi all'interno di un repository git e si desideri confrontare i file non tracciati all'interno di quel repository. Dalle pagine man :
Questo modulo serve per confrontare i due percorsi indicati sul filesystem. È possibile omettere l'opzione --no-index quando si esegue il comando in un albero di lavoro controllato da Git e almeno uno dei punti dei percorsi all'esterno dell'albero di lavoro o quando si esegue il comando all'esterno di un albero di lavoro controllato da Git.
Puoi anche usare: colordiff : visualizza l'output di diff con i colori.
Informazioni su vimdiff : consente di confrontare i file tramite SSH, ad esempio:
vimdiff /var/log/secure scp://192.168.1.25/var/log/secure
Estratto da: http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html
Inoltre, non dimenticare mcdiff - Visualizzatore di diff interno di GNU Midnight Commander .
Per esempio:
mcdiff file1 file2
Godere!
Usa comm -13
(richiede file ordinati) :
$ cat file1
one
two
three
$ cat file2
one
two
three
four
$ comm -13 <(sort file1) <(sort file2)
four
Ecco la mia soluzione per questo:
mkdir temp
mkdir results
cp /usr/share/dict/american-english ~/temp/american-english-dictionary
cp /usr/share/dict/british-english ~/temp/british-english-dictionary
cat ~/temp/american-english-dictionary | wc -l > ~/results/count-american-english-dictionary
cat ~/temp/british-english-dictionary | wc -l > ~/results/count-british-english-dictionary
grep -Fxf ~/temp/american-english-dictionary ~/temp/british-english-dictionary > ~/results/common-english
grep -Fxvf ~/results/common-english ~/temp/american-english-dictionary > ~/results/unique-american-english
grep -Fxvf ~/results/common-english ~/temp/british-english-dictionary > ~/results/unique-british-english
sdiff -s file1 file2
stato utile.
Usando awk per questo. File di test:
$ cat a.txt
one
two
three
four
four
$ cat b.txt
three
two
one
Il awk:
$ awk '
NR==FNR { # process b.txt or the first file
seen[$0] # hash words to hash seen
next # next word in b.txt
} # process a.txt or all files after the first
!($0 in seen)' b.txt a.txt # if word is not hashed to seen, output it
I duplicati vengono emessi:
four
four
Per evitare duplicati, aggiungi ogni parola appena incontrata in a.txt seen
all'hash:
$ awk '
NR==FNR {
seen[$0]
next
}
!($0 in seen) { # if word is not hashed to seen
seen[$0] # hash unseen a.txt words to seen to avoid duplicates
print # and output it
}' b.txt a.txt
Produzione:
four
Se gli elenchi di parole sono separati da virgola, come:
$ cat a.txt
four,four,three,three,two,one
five,six
$ cat b.txt
one,two,three
devi fare un paio di giri extra ( for
loop):
awk -F, ' # comma-separated input
NR==FNR {
for(i=1;i<=NF;i++) # loop all comma-separated fields
seen[$i]
next
}
{
for(i=1;i<=NF;i++)
if(!($i in seen)) {
seen[$i] # this time we buffer output (below):
buffer=buffer (buffer==""?"":",") $i
}
if(buffer!="") { # output unempty buffers after each record in a.txt
print buffer
buffer=""
}
}' b.txt a.txt
Uscita questa volta:
four
five,six
diff a.txt b.txt
non è abbastanza?