Satırları başka bir dosyada olmayan bir dosyada almak için bir araç var mı?


Yanıtlar:


159

Evet. grepMetin 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

@ inderpreet99 Küçük harf -uargü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.
Caleb,

Dikkatli olun, grep -f O (N ^ 2) İnanıyorum: stackoverflow.com/questions/4780203/…
rogerdpack 16:15

1
diffBoru hattı bir tedavi sayesinde çalışıyor.
Felipe Alvarez

Sıralama sorununu hesaba katmak için, her dosyayı gerektiği gibi işlemden geçirmek için komut yerine işlem değiştirme özelliğini kullanabilirsiniz grep. Örnek:grep -F -x -v -f <(sort fileB) <(sort fileA)
Tony Cesaro

@TonyCesaro Veri kümeniz belirli bir sıraya sahip değilse ve kopyaların hesaba katılması gerekmiyorsa işe yarar. Kullanmanın avantajı diff, dosyadaki pozisyonun dikkate alınmasıdır.
Caleb

57

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 commfiltrelemeyi gerçekleştirebilir. Bu çekirdek çekirdeklerin bir parçasıdır.

Örnek

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ı bdosyada olmayacak a:

$ comm <(sort a) <(sort b) -3
    6

1
Bahsetmek için +1 comm; ne yazık ki, commsıralanmış dosyalar gerektirir
Arcege

11
öyleyse sırala onları? comm <(sıralama a) <(sıralama b) -1 -2
Sirex

Bu garip bir sözdizimi. <()? Çalışıyor ve anladım, ama bu tuhaflığın bir adı var mı?
mlissner

2
@mlissner <()ayrıca işlem ornatımı olarak da bilinir .
miku

1
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.
Stéphane Chazelas

32

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


Bu benim için işe yaramıyor, nedense ...
Ocak

@Jan dosyalarınız sıralanır mı? Onları nasıl sıraladınız?
JJS,

8

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

2
Eğer bunu devasa dosyalarla yapıyorsanız, o zaman bir ilişkisel diziye devasa bir dosya yüklemenin hafıza kısıtlamaları yasaklanacaktır.
Charles Duffy

4

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


2

Ayrıca vimdiff'i de düşünebilirsiniz, vim editöründeki dosyalar arasındaki farkları vurgular


1
Ancak Vimdiff'te çıkarma işlemini otomatik olarak yapmanın kolay bir yolu var mı?
Kazark
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.