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 diff
gibi diğer çözümler sunmuyoruz seçenekleri, -i
dava veya çeşitli boşluk seçeneklerini (görmezden -E
, -b
, -v
daha az sıkı eşleştirme için vs).
açıklama
Seçenekleri --new-line-format
, --old-line-format
ve --unchanged-line-format
sen yolu kontrol etmesine izin diff
benzer farklılıklar, biçimlendirir printf
biç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
%L
Belirteci 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 comm
ve join
) sadece beklenen çıktıyı üretmek sıralı kullanabilirsiniz olsa girdi <(sort ...)
yerinde sıralamak. İşte awk
keyfi 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 ll1
ve in
operatör1'i dosya1'deki satırın dosya2'de olup olmadığını belirlemek için kullanın . ( diff
Yinelemeler 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 gawk
komut satırından. Bu, split
invokasyon 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
, awk
olsa sadece POSIX / BSD split
yerine GNU sürümü.
awk 'NR==FNR{a[$0];next}!($0 in a)' file2 file1 > out.txt