Olarak adlandırılan iki dosya var "a.txt" ve "b.txt" kelime listesi var hem. Şimdi ekstra hangi kelimeleri kontrol etmek istiyorum "a.txt" ve olmayan "b.txt" .
İki sözlük karşılaştırmam gerektiğinden verimli bir algoritmaya ihtiyacım var.
Olarak adlandırılan iki dosya var "a.txt" ve "b.txt" kelime listesi var hem. Şimdi ekstra hangi kelimeleri kontrol etmek istiyorum "a.txt" ve olmayan "b.txt" .
İki sözlük karşılaştırmam gerektiğinden verimli bir algoritmaya ihtiyacım var.
Yanıtlar:
vim yüklüyse şunu deneyin:
vimdiff file1 file2
veya
vim -d file1 file2
fantastik bulacaksınız.
Bunları sıralayın ve kullanın comm
:
comm -23 <(sort a.txt) <(sort b.txt)
comm
girdi dosyalarını karşılaştırır (sıralar) ve varsayılan olarak üç sütun çıkarır: a'ya özgü satırlar, b'ye özgü satırlar ve her ikisinde bulunan satırlar. Belirterek -1
, -2
ve / veya -3
karşılık gelen çıktıyı bastırmak olabilir. Bu nedenle comm -23 a b
, yalnızca a'ya özgü girdileri listeler. <(...)
Sözdizimini dosyaları anında sıralamak için kullanıyorum, zaten sıralanmışlarsa buna ihtiyacınız yok.
comm
daha verimli çünkü işi tüm dosyayı hafızaya kaydetmeden tek bir seferde yapıyor. Büyük olasılıkla zaten sıralanmış olan sözlükler kullandığınız için sort
bunlara bile ihtiyacınız yoktur . Kullanımı grep -f file1 file2
diğer taraftan bütününü yükleyecektir file1
belleğe ve her satırı karşılaştırmak file2
çok daha az randımanlı olduğu girişler, hepsi ile. Çoğunlukla küçük, sıralanmamış için yararlıdır -f file1
.
\n
da dahil edileceğini buldum .
diff
Linux'ta iki dosyayı karşılaştırmak için aracı kullanabilirsiniz . Gerekli verileri filtrelemek için --changed-group-format ve --unchanged-group-format seçeneklerini kullanabilirsiniz.
Her seçenek için ilgili grubu seçmek üzere aşağıdaki üç seçenek kullanılabilir:
'% <' FILE1'den satır al
'%>' FILE2'den satır al
Her iki dosyadan da satırları kaldırmak için '' (boş dize).
Örn: diff --changed-group-format = "% <" --unchanged-group-format = "" dosya1.txt dosyası2.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
Fark çıktı stilini tercih git diff
ederseniz, --no-index
git deposunda olmayan dosyaları karşılaştırmak için bayrakla kullanabilirsiniz:
git diff --no-index a.txt b.txt
Her birinde yaklaşık 200 bin dosya adı dizesi bulunan birkaç dosya kullanarak, time
bu yaklaşımı (diğer yerleşik komutla) karşılaştırdım ve buradaki diğer yanıtlardan bazıları:
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
farkla en hızlı çıktı gibi gözükse de, git diff --no-index
fark tarzı çıktı için en hızlı yaklaşım gibi görünmektedir.
Güncelleme 2018-03-25--no-index
Bir git deposunun içinde değilseniz ve bu depodaki izlenmemiş dosyaları karşılaştırmak istemiyorsanız bayrağı atlayabilirsiniz . Gönderen man sayfaları :
Bu form, dosya sisteminde verilen iki yolu karşılaştırmak içindir. Komut Git tarafından kontrol edilen bir çalışma ağacında ve çalışma ağaçlarının dışındaki yol noktalarından en az birini çalıştırırken veya Git tarafından kontrol edilen bir çalışma ağacının dışında komutu çalıştırırken --no-index seçeneğini atlayabilirsiniz.
Şunları da kullanabilirsiniz: colordiff : Farkın çıktısını renklerle görüntüler.
Hakkında vimdiff : Bu örneğin, SSH üzerinden dosya karşılaştırma yapmanızı sağlar:
vimdiff /var/log/secure scp://192.168.1.25/var/log/secure
Alıntı: http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html
Ayrıca, mcdiff - GNU Midnight Commander'ın dahili dif görüntüleyicisini de unutmayın .
Örneğin:
mcdiff file1 file2
Zevk almak!
Kullan comm -13
(sıralanmış dosyalar gerektirir) :
$ cat file1
one
two
three
$ cat file2
one
two
three
four
$ comm -13 <(sort file1) <(sort file2)
four
İşte bunun için benim çözüm:
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
faydalı oldu.
Bunun için awk kullanma. Test dosyaları:
$ cat a.txt
one
two
three
four
four
$ cat b.txt
three
two
one
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
Kopyalar çıktı olarak verilir:
four
four
Yinelemeleri önlemek için, yeni bir araya getirilen her kelimeyi seen
karma olarak a.txt dosyasına ekleyin :
$ 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
Çıktı:
four
Kelime listeleri virgülle ayrılmışsa, örneğin:
$ cat a.txt
four,four,three,three,two,one
five,six
$ cat b.txt
one,two,three
birkaç ekstra tur ( for
döngüler) yapmanız gerekiyor :
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
Bu seferki çıktı:
four
five,six
diff a.txt b.txt
yeterli değil?