GNU diffçıktısında eski / yeni / değişmemiş çizgilerin biçimlendirmesini kontrol ederek bunu başarabilirsiniz :
diff --new-line-format="" --unchanged-line-format="" file1 file2
Bunun çalışması için girdi dosyaları sıralanmalıdır . İle bash(ve zsh) sen yerinde süreç ikamesi ile sıralayabilir <( ):
diff --new-line-format="" --unchanged-line-format="" <(sort file1) <(sort file2)
Yukarıdaki yeni ve değişmemiş çizgiler bastırılır, bu nedenle yalnızca değiştirilen (yani, durumunuzdaki kaldırılan çizgiler) çıkarılır. Ayrıca birkaç kullanabilir diffgibi diğer çözümler sunmuyoruz seçenekleri, -idava veya çeşitli boşluk seçeneklerini (görmezden -E, -b, -vdaha az sıkı eşleştirme için vs).
açıklama
Seçenekleri --new-line-format, --old-line-formatve --unchanged-line-formatsen yolu kontrol etmesine izin diffbenzer farklılıklar, biçimlendirir printfbiçim belirteçleri. Bu seçenekler yeni (eklenmiş), eski (kaldırılmış) ve değiştirilmemiş formatlar sırasıyla satırları . Birini "" boş olarak ayarlamak, bu tür hatların çıkışını engeller.
Eğer aşina değilseniz birleşik fark biçimi, sen kısmen bunu birlikte yeniden oluşturabilirsiniz:
diff --old-line-format="-%L" --unchanged-line-format=" %L" \
--new-line-format="+%L" file1 file2
%LBelirteci Söz konusu satır ve biz "+" "her önüne - gibi" veya "" diff -u
(yalnızca çıkış farklılıklar, bu yoksun olduğunu not --- +++ve @@her gruplandırılmış değişim üstündeki çizgiler). Ayrıca gibi diğer yararlı şeyler yapmak için kullanabilir sayı her satırı ile %dn.
diff(Diğer önerilerle birlikte yöntem commve join) sadece beklenen çıktıyı üretmek sıralı kullanabilirsiniz olsa girdi <(sort ...)yerinde sıralamak. İşte awkkeyfi olarak sıralanan girdi dosyalarını kabul eden ve eksik satırları dosya1'de göründükleri sırayla çıkaran basit (nawk) bir komut dosyası (Konsolebox'ın cevabında bağlantılı olan komut dosyalarından esinlenilmiştir) .
# output lines in file1 that are not in file2
BEGIN { FS="" } # preserve whitespace
(NR==FNR) { ll1[FNR]=$0; nl1=FNR; } # file1, index by lineno
(NR!=FNR) { ss2[$0]++; } # file2, index by string
END {
for (ll=1; ll<=nl1; ll++) if (!(ll1[ll] in ss2)) print ll1[ll]
}
Bu, dosya1 içeriğinin tamamını satır satır dizinli bir dizide ll1[]satır satır ve dosya2 içeriğinin tamamını satır satır dizinli ilişkilendirilebilir dizide saklar ss2[]. Her iki dosya da okunduktan sonra yineleyin ll1ve inoperatör1'i dosya1'deki satırın dosya2'de olup olmadığını belirlemek için kullanın . ( diffYinelemeler varsa , bu yöntem için farklı bir çıktı olacaktır .)
Dosyaların her ikisini de saklamak bellek sorununa neden olacak kadar büyükse, yalnızca dosya1 depolayarak ve dosya2 okunduğunda eşleşmeleri silerek CPU'yu bellek için takas edebilirsiniz.
BEGIN { FS="" }
(NR==FNR) { # file1, index by lineno and string
ll1[FNR]=$0; ss1[$0]=FNR; nl1=FNR;
}
(NR!=FNR) { # file2
if ($0 in ss1) { delete ll1[ss1[$0]]; delete ss1[$0]; }
}
END {
for (ll=1; ll<=nl1; ll++) if (ll in ll1) print ll1[ll]
}
Yukarıda, dosya1'in tüm içeriği biri satır numarasına ll1[]göre dizinlenmiş, biri satır içeriğine göre dizinlenmiş iki dizide depolanır ss1[]. Dosya2 okunur Sonra, her bir eşleşen satır silinir ll1[]ve ss1[]. Sonunda, dosya1'den kalan satırlar çıktı ve orijinal sıra korunur.
Bu durumda, belirtildiği gibi sorunla, GNU (filtreleme bir GNU uzantısıdır) kullanarak bölünebilir ve fethedebilirsinizsplit , dosya1 parçalarıyla her seferinde çalışır ve dosya2'yi her seferinde tamamen okuyabilirsiniz:
split -l 20000 --filter='gawk -f linesnotin.awk - file2' < file1
Kullanımı ve yerleştirme uygulaması -anlam stdinüzerinde gawkkomut satırından. Bu, splitinvokasyon başına 20000 satırlık parçalarda dosya1 tarafından sağlanır .
GNU dışı sistemlerde kullanıcılar için, neredeyse kesinlikle yoktur bir GNU coreutils parçası olarak OSX'te dahil, edinmek paketlediğinizden Apple Xcode GNU sağlar araçları diff, awkolsa sadece POSIX / BSD splityerine GNU sürümü.
awk 'NR==FNR{a[$0];next}!($0 in a)' file2 file1 > out.txt