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)
commconfronta 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, -2e / o -3è possibile sopprimere l'output corrispondente. Pertanto comm -23 a belenca 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 sortloro. L'uso grep -f file1 file2d'altro canto caricherà l'intero file1in memoria e confronterà ogni riga file2con tutte quelle voci, il che è molto meno efficiente. È utile soprattutto per piccoli, non ordinati-f file1 .
\nsarà incluso anche per fare il confronto.
È possibile utilizzare lo diffstrumento 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-indexflag 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 timecomando 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
commsembra essere di gran lunga il più veloce, mentre git diff --no-indexsembra essere l'approccio più veloce per l'output in stile diff.
Aggiornamento 25-03-2018 È possibile omettere il --no-indexflag 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 file2stato 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 seenall'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 ( forloop):
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.txtnon è abbastanza?