BÜYÜK metin dosyasında 'head' veya 'tail' kullanma - 19 GB


15

Çok büyük bir metin dosyasının parçalarını görüntüleme ile ilgili bir sorunum var. Bu dosya, yaklaşık 19 GB, herhangi bir geleneksel yolla görüntülenemeyecek kadar büyük.

Ben denedim head 1ve tail 1( head -n 1ve tail -n 1) her iki komut ile çeşitli şekillerde (ortada bir parça almak için) birlikte şanssız piped ile. Ubuntu 9.10 çalıştıran Linux makinem bu dosyayı işleyemiyor.

Bu dosyayı nasıl kullanırım? Nihai hedefim 45000000 ve 45000100 hatlarına girmek.


Çizgileri okumak ve dosyaya ihtiyacım olanları yazdırmak için hızlı bir Python betiği yazmayı düşünüyorum, ancak bunun uzun zaman
aldığını

Tüm çizgiler aynı uzunlukta mi?
Paul

@Paul - ne yazık ki, aynı uzunlukta değiller.
nicorellius

Deneyebilirsin splitile çalışmalarına büyük dosya kolaylaştırmak için.
iglvzx

1
Tamam. Büyük bir dosyanın işlenmesi zaman alacaktır, bu nedenle aşağıdaki yanıtlar size yardımcı olacaktır. Sadece aradığınız parçayı çıkarmak istiyorsanız ve nerede olduğunuzu yaklaşık olarak tahmin edebiliyorsunuz dd. Örneğin dd if=bigfile of=extractfile bs=1M skip=10240 count=5, 10GB noktasından başlayarak dosyadan 5MB çıkarır.
Paul

Yanıtlar:


11

Kullanmalısınız sed.

sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines

Bu sed45000000-45000100 dahil satırları yazdırmayı ve 45000101 satırından çıkmayı söyler.


1
Hala çok yavaş, neredeyse kafa -45000000,45000100p bigfile gibi | kuyruk -100> kurtarılmış hatlar
Dmitry Polushkin

tail+|head% 10-15 oranında daha hızlıdır.
Erich

4

Tek bir alana sahip tek bir tablo ile bir MySQL veritabanı oluşturun. Ardından dosyanızı veritabanına alın. Bu, belirli bir çizgiye bakmayı çok kolay hale getirecektir.

Başka bir şeyin daha hızlı olabileceğini düşünmüyorum ( headve tailzaten başarısız olursa). Sonunda, satır bulmak isteyen uygulama yeni satırlar nbulunana kadar tüm dosyayı aramak zorundadır n. Bir çeşit arama olmadan (dosyaya ofset bayt satır-endeksi) daha iyi bir performans elde edilemez.

Bir MySQL veritabanı oluşturmanın ve içine veri aktarmanın ne kadar kolay olduğu düşünüldüğünde, bunun uygulanabilir bir yaklaşım olduğunu hissediyorum.

İşte nasıl yapılacağı:

DROP DATABASE IF EXISTS helperDb;
CREATE DATABASE `helperDb`;
CREATE TABLE `helperDb`.`helperTable`( `lineIndex` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `lineContent` MEDIUMTEXT , PRIMARY KEY (`lineIndex`) );
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable (lineContent);
SELECT lineContent FROM helperTable WHERE ( lineIndex > 45000000 AND lineIndex < 45000100 );

/tmp/my_large_file okumak istediğiniz dosya olurdu.

Her satırda sekmeyle ayrılmış değerleri olan bir dosyayı içe aktarmak için doğru sözdizimi şöyledir:

LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable FIELDS TERMINATED BY '\n' (lineContent);

Bunun bir diğer önemli avantajı, daha sonra başka bir satır kümesi çıkarmaya karar verirseniz, işlem için tekrar saatlerce beklemek zorunda kalmamanızdır (elbette veritabanını silmediğiniz sürece).


Yani bu gerçekten iyi bir çözüm. sedAşağıdaki komutla çalışmayı başardım ve satırlarımı belirledim. Ama şimdi veritabanı yöntemi için daha uygun olabilir bir takip sorum var. Şimdi dosyadan birkaç yüz satır silmem gerekiyor.
nicorellius

Bunu sedda yapabileceğime eminim . Tabii ki, veritabanında veri olsaydı, sadece istediğiniz satırlarla yeni bir dosyayı dışa aktarmak önemsiz olurdu.
Der Hochstapler

Tekrar teşekkürler. sedCevabı aldım (çünkü bana daha fazla zevk verdi; -) ama size yukarı oy verdim çünkü gelecekte yönteminizi kullanacağım. Bunu takdir ediyorum.
nicorellius

1
Sen a eklemeyi deneyebilirsiniz FIELDS TERMINATED BY '\n'için LOAD DATAhat.
Der Hochstapler

1
Üzgünüm, kodumda bir hata oluştu. Ayrıca davanız için doğru sözdizimini de ekledim (bu sefer test edildi).
Der Hochstapler

1

Büyük dosyalar için iki iyi eski araç joinve split. Bölmeyi, --lines=<number>dosyayı belirli boyuttaki birden çok dosyaya kesen seçenekle kullanabilirsiniz .

Örneğin split --lines=45000000 huge_file.txt. Ortaya çıkan parçalar xa, xb, vb. Olacaktır. Sonra istediğiniz çizgileri içeren xbhead parçasını yapabilirsiniz . Ayrıca dosyaları tek bir büyük dosyaya tekrar 'birleştirebilirsiniz'.


Harika, teşekkürler, split komutunu tamamen unuttum.
siliconrockstar

0

Doğru araçlara sahipsiniz ancak yanlış kullanıyorsunuz. Daha önce U&L'de yanıtlandığı gibi tail -n +X file | head -n Y(not +) sedX'ten başlayan Y hatlarına göre% 10-15 daha hızlıdır . Ve rahatlıkla, exitişlemi olduğu gibi açıkça yapmak zorunda değilsiniz sed.

tail ilk X-1 satırlarını okuyacak ve atacaktır (bunun etrafında bir yol yoktur), ardından aşağıdaki satırları okuyup yazdırın. kafa istenen sayıda satırı okuyup yazdıracak, sonra çıkacaktır. Kafa çıktığında, kuyruk bir SIGPIPE sinyali alır ve ölür, bu nedenle girdi dosyasından arabellek boyutunun değerinden (tipik olarak birkaç kilobayt) fazla satır okumaz.

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.