Tüm dosya satırlarının farklı dosyada olup olmadığını kontrol edin


15

İki dosyam var: yaklaşık 1000 satırlı dosya1 ve birkaç yüz satırlı dosya2. Dosya2'deki tüm dosya satırlarının dosya1'de olup olmadığını kontrol etmek istiyorum. Yani: ∀ satır ℓ ∈ dosya2: ℓ ∈ dosya1

Bu sembollerin ne anlama geldiğini veya "dosya1'deki tüm dosya2 satırlarının olup olmadığını kontrol edin" ne anlama geldiğini bilmiyorsa: Dosyalardan herhangi birinin eşdeğer satırları, denetimin dosyaların gereksinimi karşılayıp karşılamadığını etkilemez.

Bunu nasıl yaparım?


2
Bu dosyalar yinelenen satırlara sahip olabilir mi? Eğer file22 satır içeriyor Ami ihtiyacı var, file1en az 2 hatlarını içerecek şekilde A?
Stéphane Chazelas

2
@ StéphaneChazelas Tüm satırların (her iki dosyada) benzersiz olması garanti edilir.
UTF-8

1
@ UTF-8 Bu, sorunuzda düzenleme yapmak için önemli bir ayrıntı olacaktır.
David Z

2
@DavidZ Artık mevcut cevaplar bu garantiye güvenmediği için değil. Şimdi soruyu düzenleyerek cevapların görünür kapsamını azaltacağım.
UTF-8

@ UTF-8 Sanırım, soru onsuz biraz belirsiz olsa da, örneğin belirli bir satır dosya2'de 5 kez oluşursa, bu satırın da dosya1'de 5 kez olması gerekir mi (sadece bir kere değil)? Bu gereksinime sahip olsaydınız, mevcut cevapların hiçbirinin işe yaramayacağı gibi görünmüyor, bu yüzden en azından kastettiğiniz şeyin bu olmadığını açıkça belirten bir şeyde düzenlemenizi öneririm.
David Z

Yanıtlar:


19
comm -13 <(sort -u file_1) <(sort -u file_2)

Bu komut, benzersiz satırlar çıkarır file_2. Dolayısıyla, çıktı boşsa, tüm file_2satırlar file_1.

Comm'nun adamından:

   With  no  options,  produce  three-column  output.  Column one contains
   lines unique to FILE1, column two contains lines unique to  FILE2,  and
   column three contains lines common to both files.

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

@don_crissti Doğru. Düzeltildi: komuta -ueklenen seçenek sort. Şimdi, her iki sıralı dosyada yalnızca benzersiz satırlar kalır.
MiniMax

Çok basit bir çözüm! Bu sözdizimi dosyaları bekleyen herhangi bir program için geçerli mi? Ben her zaman <borunun stdin olduğunu düşündüm . Parantez terimi bunu değiştiriyor mu?
UTF-8

2
@ UTF-8 Buna işlem ikamesi denir . Buradan okuyabilirsiniz . Ve evet, geçici bir dosya gibi davranır, bu nedenle dosyaları bekleyen herhangi bir programdaki gerçek dosyalar yerine kullanılabilir.
MiniMax

Bu sık sık yaptığınız bir file_1şeyse, sunulmuş formda saklamak isteyebilirsiniz . Yazma ve zamandan tasarruf sağlar.
Stig Hemmer

7
@minimax "Herhangi" dışında iyi yorum. Harika olsa da, işlem ikamesi her durumda kullanılamaz, çünkü elde edilen "dosyalar" gerçek dosyalar değil akışlardır. Bu, normal bir dosya gibi "aranamayacakları" anlamına gelmez ve yalnızca program dosyayı başlangıçtan itibaren normal bir şekilde okuduğunda kullanılabilir ve program belirli bir noktaya veya baştan başlamak için geri sarma. Ne mutlu ki, çoğu program sadece dosyalarını okur () ve bu nedenle süreç ikamesi çoğu programla çalışır, ancak "herhangi bir" programla çalışmaz.
Law29

7
[ $(grep -cxFf file2 <(sort -u file1)) = $(sort -u file2 | wc -l) ] && 
  echo all there || 
  echo some missing

Dosya1 dosyasındaki (benzersiz satırları) dosya2'deki eşleşme sayısı dosya2'deki benzersiz satırların sayısı ile aynıysa, hepsi oradadır; aksi halde değildirler.


5

GNU'nun awkbelirli bir length(array)özelliği (ve destekleyebilecek başka bir awkuygulamayı) desteklediği yerlerde kullanmak ve dosyalar sıralanırsa gerekli değildir.

gawk 'FNR==NR{seen[$0];next} ($0 in seen){delete seen[$0]};
    END{print (!length(seen))?"Matched":"Not Matched"}' file2 file1

Bu, file2'yiseen , dosya2'nin tüm satırı olarak anahtarla adlandırılan bir diziye okuyor .

Ardından file1'i okuyun ve görülen satırdaki çizgilerle eşleşirse her bir satır için o anahtarı silin.

Sonunda dizisi boş vasıtaları tüm satırları ise file2 mevcut Dosya1 ve yazdırılacaktır Matchedaksi görüntüler, Not Matched.


Tüm awkuygulamalarda uyumluluk için .

awk 'FNR==NR{seen[$0];next} ($0 in seen){delete seen[$0]};
    END{for(x in seen);print (!x)?"Matched":"Not Matched"}' file2 file1

Boş satırları / veya beyaz boşluklu satırları yalnızca dosya2'deyken yoksaymak için , diziye okumayı atlamak NFiçin koşulunu eklemeniz gerekir NR==FNR && NF {....


length(array)sadece gawk-AFAIK; kesinlikle POSIX değil.
dave_thompson_085

@ dave_thompson_085 Doğru, cevabımı güncelledim. thanks
αғsнιη

3

commBunu kullanarak her iki dosyada da ortak olan satırları bulabilirsiniz.

comm -12 file1 file2

man commDaha fazla ayrıntı için bir göz atın


Her iki dosyadaki ortak satırları döndürdüğünü düzeltin, ancak bu OP2'nin Q'suna, dosya2'de dosya1'de çıkmayan bir satırınız varsa, dosya2'deki tüm satırların dosya1'de bulunmadığı bir yanıt sağlamaz.
αғsнιη

1
dosyalar sıralanmalıdır. Adamdan " comm- iki sıralı dosyayı satır satır karşılaştır".
MiniMax

@MiniMax haklı. Bu işe yaramıyor. Kullanılan diğer cevap comm, açıkça yanlış olmayan bir çözüm içeriyor. Komutunuzu çalıştırdığımda, dosyaların sıralanmış düzende olmadığına ve her iki dosyada da kesinlikle çok sayıda satıra sahip olduğuna dair uyarılar alıyorum.
UTF-8

3
diff -q <(sort -u file2) <(grep -Fxf file2 file1 | sort -u)

eğer herhangi bir çıktı üretecek file1içeren tüm satırları içinde file2ve statü ile çıkış 0aksi takdirde böyle bir şey yazdırır,

Files /proc/self/fd/11 and /proc/self/fd/12 differ

ve durumla çıkış 1


2

Bir Python programı kullanın:

#!/usr/bin/env python3
import sys

def open_arg(path):
    return sys.stdin if path == '-' else open(path)

def strip_linebreak(s):
    return s[:-1] if s.endswith('\n') else s

with open_arg(sys.argv[1]) as pattern_file:
    patterns = set(map(strip_linebreak, pattern_file))

with open_arg(sys.argv[2]) as dataset_file:
    for l in map(strip_linebreak, dataset_file):
        patterns.remove(l)
        if not patterns:
            break

sys.exit(int(bool(patterns)))

Kullanımı:

python3 contains-all.py file2 file1

Program çıkış durumu, 2. dosyadaki tüm kalıpların eşleşip eşleşmediğini gösterir:

  • 0 (başarı) tüm kalıpların eşleştiği anlamına gelir.
  • 1 (başarısızlık) bazı kalıpların eşleşmediği anlamına gelir.

Kabuktaki (komut dosyasında) çıkış durumunu sorgulamak için $?özel değişkeni veya komut çıkış durumunu değerlendiren diğer ifadeleri kullanabilirsiniz , örneğin kısa devre operatörleri &&ve veya ||gibi koşullu ifadeler . Misal:ifwhile

if python3 compare-all.py file2 file1 && some-other --condition; then
    # do stuff
fi

1

combinedan moreutils size tüm satırları gösterecektir içinde file2o olmayan file1ile:

combine file2 not file1

Ardından, boru sayısını şu şekilde borulandırarak sayabilirsiniz wc -l:

if [ $(combine file2 not file1 | wc -l) != 0 ]; then
  echo "lines missing"
else
  echo "You're fine"
fi
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.