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)
commgirdi 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, -2ve / veya -3karşı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.
commdaha 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 sortbunlara bile ihtiyacınız yoktur . Kullanımı grep -f file1 file2diğer taraftan bütününü yükleyecektir file1belleğ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.
\nda dahil edileceğini buldum .
diffLinux'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 diffederseniz, --no-indexgit 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, timebu 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
commfarkla en hızlı çıktı gibi gözükse de, git diff --no-indexfark 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 file2faydalı 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 seenkarma 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 ( fordö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.txtyeterli değil?