A dosyasının içerdiği, ancak B dosyasının almadığı satırları alabilen herhangi bir araç var mı? Örneğin perl ile basit bir senaryo yazabilirim, ama eğer böyle bir şey varsa, zamanımı kazanacağım.
A dosyasının içerdiği, ancak B dosyasının almadığı satırları alabilen herhangi bir araç var mı? Örneğin perl ile basit bir senaryo yazabilirim, ama eğer böyle bir şey varsa, zamanımı kazanacağım.
Yanıtlar:
Evet. grep
Metin dizeleri için dosyaları aramak için standart bir araç, bir dosyadaki tüm satırları diğerinden çıkarmak için kullanılabilir.
grep -F -x -v -f fileB fileA
Bu, fileB'deki her satırı bir pattern ( -f fileB
) kullanarak ve eşleşecek şekilde (normal bir regex değil) ( -F
) eşleştirmek için düz bir dize olarak kabul ederek çalışır . Eşleşmeyi tüm satırda ( -x
) olmaya zorlar ve yalnızca eşleşmeyen satırları ( ) yazdırırsınız -v
. Bu nedenle, fileA dosyasındaki, fileB dosyasındaki herhangi bir satır ile aynı verileri içermeyen satırları yazdırıyorsunuz.
Bu çözümün dezavantajı, satır sırasını hesaba katmaması ve girişinizin farklı yerlerde yinelenen satırları olması durumunda, beklediğiniz şeyi alamayabilirsiniz. Bunun çözümü gibi gerçek bir karşılaştırma aracı kullanmaktır diff
. Daha sonra, dosya, satırların% 100 bağlam değerine sahip bir fark dosya oluşturma B dosya dosya A dönüştürme kaldırılabilir tıpkı hatları için ayrıştırma yapabileceğini (bu komut da diff kaldırır doğru satırları aldıktan sonra biçimlendirme.)
diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
-u
argümanı aslında bir boşluk tarafından takip edilmediği sürece bir sayının parametresini alır. Daha önce sahip olduğum yolun avantajı, değeri olan veya olmayan bir değerde çalışacağı için, bu alt komut yordamında çıktısını almayan bir şey kullanabilirsiniz. Büyük harf '-U' ise bir argüman gerektirir.
diff
Boru hattı bir tedavi sayesinde çalışıyor.
grep
. Örnek:grep -F -x -v -f <(sort fileB) <(sort fileA)
diff
, dosyadaki pozisyonun dikkate alınmasıdır.
Cevap, karşılaştırdığınız dosyaların türüne ve biçimine büyük ölçüde bağlıdır.
Karşılaştığınız dosyalar metin dosyaları halinde sıralanırsa, Richard Stallman ve Davide McKenzie tarafından yazılan GNU aracı aradığınız comm
filtrelemeyi gerçekleştirebilir. Bu çekirdek çekirdeklerin bir parçasıdır.
Aşağıdaki 2 dosyanızın olduğunu söyleyin:
$ cat a
1
2
3
4
5
$ cat b
1
2
3
4
5
6
Dosyadaki Hatları b
dosyada olmayacak a
:
$ comm <(sort a) <(sort b) -3
6
comm
; ne yazık ki, comm
sıralanmış dosyalar gerektirir
<()
? Çalışıyor ve anladım, ama bu tuhaflığın bir adı var mı?
comm
İlk olarak 1973 dolaylarında, Bell Laboratuvarlarında bulunan bir kişi tarafından yazılmış, rms değil. Daha sonra gelen GNU uygulamasına atıfta bulunuyorsunuz. Unix tesislerinin yıllar boyunca birçok farklı uygulaması olmuştur.
yığın akışından ...
comm -23 dosya1 dosya2
-23, her iki dosyadaki veya yalnızca 2. dosyadaki satırları bastırır. Dosyaların sıralanması gerekir (bunlar sizin örneğinizdedir), ancak değilse, bunları önce sıralayın ...
Buradaki man sayfasına bakın
Grep ve comm (sort ile) yöntemleri büyük dosyalarda uzun zaman alır. SiegeX ve ghostdog74 , Stack Overflow'taki iki dosyadan birine özgü satırları çıkarmak için iki harika awk yöntemini paylaştı :
$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
Dosyalar büyükse ve girişleriniz için özel bir siparişiniz yoksa, grep çok uzun sürer. Hızlı bir alternatif olacaktır
sort file1 > 1
sort file2 > 2
diff 1 2 | grep "\>" | sed -e 's/> //'
[file2-file1 ekrana, boruya dosya vb.]
Değişen >
için <
ters çıkarma tanınacak.rm 1 2