Dizeleri çok büyük bir dosyaya değiştirme


10

Ben aşağıdaki gibi aynı biçimde, hiçbir ayırıcı karakter ile URL çok uzun bir dizi var:

http://example.comhttp://example.nethttp://example.orghttp://etc...

Her URL'nin yeni bir satırda olmasını istiyorum. Sed kullanarak "http: //" tüm örneklerini "\ nhttp: //" ile değiştirerek yapmaya çalıştım

sed 's_http://_\nhttp://_g' urls.txt

ancak bir segmentasyon hatası oluşur (bellek ihlali). Ben sadece dosya büyüklüğü (100GB üzerinde) sed bazı sınırı aşmasına neden olduğunu tahmin edebilirsiniz.

Dosyayı işlenmek üzere birkaç küçük dosyaya bölebilirim, ancak tüm "http: //" örneklerinin sağlam kalması gerekir.

Bunu yapmanın daha iyi bir yolu var mı?


Sed, ara belleğinde tek bir satırı okumaya çalışırken satır sonu olmayan 100GB'ı sevmediğini düşünüyorum.
jippie

bölme (kesim "nerede" olursa olsun), işleme, sonra yeniden montaj doğru sonuç vermelidir.
enzotib

3
Tek bir uzun satır içeren 100 GB'lık bir metin dosyanız varsa, işi yapmak için hızlı bir C programı yazmaktan daha iyidir.
fpmurphy

Yanıtlar:


11

İle awkaynı anda çok miktarda metin okumaktan kaçınabilirsiniz:

awk -vRS='http://' -vORS='\nhttp://' 1 urls.txt > urlsperline.txt

Başarı, kullanılan awkuygulamaya bağlı olabilir . Örneğin gawkiyi çalışıyor, ancak mawkçöküyor.


6

Bu işi yapacak:

perl -pe 'BEGIN { $/ = "//" } s!(?=http://\z)!\n!' urls.txt

Ayarlayarak $ / o ile biten bu yüzden, bir çizgi tanımını değiştirdik //yerine yeni satır. Bu Perl'in her seferinde bir URL okumasını sağlar. Bir URL'nin //şemadan sonra dışında olması olası değildir , ancak varsa, normal ifade URL'nin sahte yeni satırlar eklemesini engeller.

İlk URL'nin önüne boş bir satır eklemekten kaçınmak istiyorsanız:

perl -pe 'BEGIN { $/ = "//"; print scalar <> } s!(?=http://\z)!\n!' urls.txt

Daha s!http://\z!\nhttp://!hızlı olup olmadığını görmek için karşılaştırmayı deneyebilirsiniz . Eşdeğerler. /gHer "satır" için yalnızca bir eşleşme olabileceğinden bayrağın ikame için gerekli olmadığını unutmayın .


Perl regexp motoru çok gigabayt uzunluğunda çizgilerle iyi mi?
Alexios

2
@Alexios, muhtemelen değil, ama olması gerekmez. Değiştiğimden beri $/, her seferinde yalnızca bir URL ile uğraşacak.
cjm

Ah, orada ne yaptığını görüyorum. 90'lı yıllardan bu yana bir süre geçti ve mecburdum man perlvar, ama bu mantıklı geliyor.
Alexios

Linux, URL'lerin yollara birden fazla eğik çizgi yerleştirmesine izin verir, bu nedenle bunlardan herhangi birine sahipseniz bu kod başarısız olabilir. Tüm dizeyi (http ve tümünü) test etmekte bu sorun olmaz.
Joe

@Joe, http:normal ifadedeki kısmı test ediyorum . Her birini inceleyecek //, ancak bulmadıkça yeni satır eklemeyecektir http://.
cjm

5
  1. :Dosyayı kesmek için a'nın tüm satırlarını yeni satırla değiştirin .
  2. değiştirmek
    • http ile hattın sonunda
    • bir yeni satır izler http:ve bir sonraki satırı ekler
  3. Bir kez tekrarlayın, böylece çift ve tek satırlar güncellenir

Bu adımlar şöyle görünür:

tr ':' '\n' | sed -e '/http$/{N;s/http\n/\nhttp:/}' | sed -e '/http$/{N;s/http\n/\nhttp:/}'
  1. Başlamayan satırlar olup olmadığını kontrol edin http://, satır numaralarını yazdırın. Bu yalnızca a:, URL'nin dışında http.

    grep -nv '^http://'

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.