Sıralı dosyayı verimli bir şekilde ara


12

Her satırda bir dize içeren büyük bir dosya var. Hızlı bir şekilde dosyada bir dize olup olmadığını belirlemek istiyorum. İdeal olarak, bu bir ikili kesme türü algoritması kullanılarak yapılacaktır.

Bazı Google çalışanları, bir ikili arama algoritması kullanarak belirli bir önekle başlayan tüm dizeleri bulmayı ve çıkarmayı vaat lookeden -bbayrağı içeren komutu ortaya çıkardı . Ne yazık ki, düzgün çalışmıyor gibi görünüyor ve dosyada olduğunu bildiğim dizeleri için null sonuçlar döndürür (eşdeğer greparama tarafından düzgün döndürülür ).

Herkes bu dosyayı verimli bir şekilde aramak için başka bir yardımcı program veya strateji biliyor mu?


Üst yanıt yanlış sıralamayı belirtir: gerçek şu şekilde sıralamanız gerekir: LC_COLLATE = C lookkomutun düzgün çalışması için sort -d , çünkü görünüm yerel ayarı görmezden geliyor ve sadece sabit kodlu sıralama gibi C kullanıyor, ben de bir hata açtım Bu kafa karıştırıcı davranış nedeniyle: bugzilla.kernel.org/show_bug.cgi?id=198011
Sur3

look -bbir hata ile benim için başarısız oldu File too large. Sanırım her şeyi belleğe okumaya çalışıyor.
Brian Minton

Yanıtlar:


9

grepVe arasında önemli bir fark vardır look:

Aksi açıkça belirtilmedikçe grep, çizgiler içinde bir yerde bile desenler bulur. İçin lookmanpage devletler:

look - belirli bir dizeyle başlayan satırları görüntüle

lookÇok sık kullanmıyorum , ama yeni denediğim önemsiz bir örnek üzerinde işe yaradı.


1
Aramam gereken dosyanın yaklaşık 110.000.000 satırı var. Eğer yaparsam egrep "^TEST" sortedlist.txt | wc -l 41.289 sonuç alırım. Ancak eşdeğer lookkomutlar look -b TEST sortedlist.txt | wc -lsadece 1995 sonucunu verir. Neredeyse bir hata olup olmadığını merak ediyorum look.
Matt

1
@Matt Belki lookde dosyayı sıralamak için kullandığınız programdan farklı harmanlama ayarları kullanıyor olabilir.
kasperd

4

Belki biraz geç cevap:

Sgrep size yardımcı olacaktır.

Sgrep (sıralanmış grep), sıralanmış giriş dosyalarında bir arama anahtarıyla eşleşen satırları arar ve eşleşen satırları çıkarır. Büyük dosyaları ararken sgrep geleneksel Unix grep'ten çok daha hızlıdır, ancak önemli kısıtlamalar vardır.

  • Tüm girdi dosyaları normal dosyalar olarak sıralanmalıdır.
  • Sıralama anahtarı satırın başından başlamalıdır.
  • Arama tuşu yalnızca satırın başında eşleşir.
  • Düzenli ifade desteği yok.

Kaynağı buradan indirebilirsiniz: https://sourceforge.net/projects/sgrep/?source=typ_redirect

ve buradaki belgeler: http://sgrep.sourceforge.net/

Diğer yol:

Dosya ne kadar büyük olduğunu bilmiyorum. Belki paralel denemek gerekir:

/programming/9066609/fastest-possible-grep

Her zaman 100GB'dan büyük dosyalar ile grep yapıyorum, iyi çalışıyor.



evet, indirme bağlantısını dolduruyorum ...
memorybox

Bu kadarsa, yeni bir yanıt göndermek yerine bu yayını düzenlemelisiniz .
muru

bu yazı tavsiye: sudo apt-get install sgrep sgrep almak için, buntu depolarındaki sgrep aslında bu sgrep değil, aynı şey olduğundan emin değilim.
memorybox

0

Dosyayı parçalara ayırabilir ve sonra sadece istediğiniz parçayı grep edebilirsiniz:

for line in $(cat /usr/share/dict/american-english | tr '[:upper:]' '[:lower:]' | sort | uniq)
do
    prefix=$(echo $line | md5sum - | cut -c 1-2)
    mkdir -p $prefix
    echo $line | gzip >> $prefix/subwords
done

o zaman arama şöyle görünecektir:

    prefix=$(echo $word | md5sum - | cut -c 1-2)
    zgrep -m 1 -w word $prefix/subwords

Bu iki şey yapar:

  1. sıkıştırılmış dosyaları okuma ve yazma. Yükü disk yerine cpu (çok hızlı) üzerine koymak genellikle daha hızlıdır (çok yavaş)
  2. yaklaşık eşit bir dağılım elde etmek için hash şeyler, her parçanın boyutunu azaltmak için istediğiniz gibi daha kısa veya daha uzun bir karma kullanabilirsiniz (ancak eğer iç içe geçmiş alt dizinleri kullanmanızı öneririm)

0

sgrep sizin için işe yarayabilir:

sudo apt-get install sgrep
sgrep -l '"needle"' haystack.txt

Http://sgrep.sourceforge.net/ proje sayfası şöyle diyor:

Sgrep, çok hızlı ancak sıralı girdi gerektiren bir ikili arama algoritması kullanır.

Ancak ekleme için, bir veritabanı kullanmaktan daha iyi bir çözüm olmadığını düşünüyorum: /programming/10658380/shell-one-liner-to-add-a-line-to-a-sorted-file/ 33859372 # 33859372


3
sgrepUbuntu depolarından aslında bu sgrep "bir yapılandırılmış desen için bir dosya arama" için tasarlanmış ve ikili arama ile ilgisi vardır.
ingomueller.net

0

Gerçekten hızlı olmasını istiyorsanız (O (1) hızlı) içine bakmak için bir karma set oluşturabilirsiniz. Önceden oluşturulmuş bir karma kümesini bir dosyada saklamamı ve tüm dosyayı belleğe okumak zorunda kalmadan soruşturmamı sağlayacak bir uygulama bulamadım , bu yüzden kendimi yuvarladım .

Karma kümesini ( -b/ --build) oluşturun:

./hashset.py --build string-list.txt strings.pyhashset

Karma setini araştırın ( -p/ --probe):

./hashset.py --probe strings.pyhashset \
    'Is this string in my string list?' 'What about this one?'

… Veya standart girdiye bakmak için dizeyle:

printf '%s\n' 'Is this string in my string list?' 'What about this one?' |
./hashset.py --probe strings.pyhashset

Yalnızca çıkış durumuyla ilgileniyorsanız --probe, -q/ --quietseçeneği ile çıktısını sessizleştirebilirsiniz :

if ./hashset.py --quiet --probe strings.pyhashset ...; then
    echo 'Found'
else
    echo 'Not found'
fi

Daha fazla seçenek için -h/ --helpseçeneğinden veya ekteki READMEdosyadan erişilebilen kullanım açıklamasına bakın .

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.