Metni çok büyük bir dosyada hızla değiştirin


25

Yalnızca birkaç satırda değiştirilen bir dize gerektiren 25 GB metin dosyasına sahibim. sedBaşarıyla kullanabilirim ancak çalışması çok uzun sürüyor.

sed -i 's|old text|new text|g' gigantic_file.sql

Bunu yapmanın daha hızlı bir yolu var mı?


Değiştirilecek metnin satır numaralarını biliyor musunuz? Hızlandırmak için tek seçeneğiniz yoksa, daha hızlı bir bilgisayar elde etmektir. Büyük miktarda veriye sahip olmanız, üzerinde arama yapmanın çok zaman alacağı anlamına gelir.
David King,

Satır numaralarını oldukça çabuk bilebilirim, yani evet.
eisaacson

Ayrıca hızlandırmak için birden fazla CPU çekirdeği kullanabilirsiniz - rankfocus.com/use-cpu-cores-linux-commands
ahaswer 20

Büyük dosyalar için sed kullanmayın. Bunun yerine vi veya vim'e bir bakın .
MikeJamam5656

Yanıtlar:


26

Deneyebilirsin:

sed -i '/old text/ s//new text/g' gigantic_file.sql

Bu referanstan :

HIZ İÇİN OPTİMİZASYON: Eğer yürütme hızının arttırılması gerekiyorsa (büyük giriş dosyaları veya yavaş işlemciler veya sabit diskler nedeniyle), "s /.../" ifadesini vermeden önce "find" ifadesi belirtilirse değiştirme işlemi daha hızlı gerçekleştirilecektir. ../" talimat.

İşte 10G dosya üzerinde bir karşılaştırma. Önce:

$ time sed -i 's/original/ketan/g' wiki10gb
real    5m14.823s
user    1m42.732s
sys     1m51.123s

Sonra:

$ time sed -i '/ketan/ s//original/g' wiki10gb
real    4m33.141s
user    1m20.940s
sys     1m44.451s

Son sedyanlış yazılmış. Bu yazıyı, dün sedolması time sed -i '/original/ s//ketan/g' wiki10gbgerekmeyen son emri düzeltmek için düzenledim time sed -i '/ketan/ s//original/g' wiki10gb. Bugün düzenlememi geri alıyorum, çünkü 1. kez artık komutla eşleşmiyor ve 2. GNU sed ile aynı testi 3+ GB dosyada yaptım ve iki sedalternatif arasında bir fark görmedim. Zamandaki farkın yanlış yazımdan kaynaklandığından şüpheleniyorum.
xhienne

@xhienne Yanlış yazım derken ne demek istediğinizi anlamadım. İlk çalıştırmada, "orjinal" kelimesini "ketan" ile değiştiriyorum, ikincisinde ise "ketan" terimini "orjinal" terimi ile değiştiriyorum, her iki durumda da eşit sayıda ornatım var.
mkc

1
Yeterli üne sahip olmayan yeni bir kullanıcı tarafından bildirilen bir "düzeltme" uyguluyordum. Şimdi ne yaptığını anladım. Bununla birlikte, bir sözdiziminin birbirinden daha iyi olduğunu kanıtlamak istiyorsanız, burada aynı olmayan aynı işlemi yapmanız gerekir (CPU-akıllı, 5 karakterli bir dizgenin aranması aynı değildir. 7 karakterli dize). Dahası, 10GB'lık bir dosyada bu tür bir test, makine yükünüze (CPU, disk) büyük ölçüde bağlıdır. timeSonuçlarda kişisel olarak çok fazla dalgalanma gördüm , ancak sonuçta, zaman içinde hiçbir fark yoktu.
xhienne

Bunun ilişkili olduğuna inanıyorum - buradaki kabul edilen cevaba bakınız, stackoverflow.com/questions/11145270/… >> sed tüm dosyayı aktarıyor, ancak bu cevabda belirtildiği gibi, satır numarasını (biliniyorsa) belirtmek yardımcı olur: benim durumumda , yürütme hızında ~ 2 kat bir artış (GNU sed 4.5). Desen aramalarını temel alarak çizgi numaralarını bulmak için -n veya ripgrep (rg) komutlarını kullanabilirsiniz. Aslında, satır numarasını belirtmek, yukarıdaki cevaba göre, bu dosya üzerinde bir arama sonucuna sahip olmak gibidir.
Victoria Stuart,

1

Kısa cevap "Hayır" dır - bu tür işlemlerde sınırlayıcı faktörünüz disk GÇ'dir. Daha hızlı bir şekilde 25GB'lık bir disk akışı mümkün değildir. Yerinde düzenleme yapmazsanız küçük bir gelişme elde edebilirsiniz ve bunun sonucunu sedayrı bir sürücüye yazarsanız (mevcut bir tane varsa) - çünkü bu şekilde birinden okurken, diğerine yazarken biraz sonuç olarak daha az çekişme.

Sen olabilir (ben çok emin ile yapabilirsiniz değilim böylece Perl kullanarak örneğin - Her hat için düzenli ifade motoru kullanarak vermeyerek onu biraz hızlandırmak mümkün sedama sözdizimi bilmiyorum) - bu başlayacaktır 10.000'den sonraki hat.

perl -pe '$. > 10_000 && s/old_text/new_text/g' 

Eğer RE'de (meta karakterlerde) herhangi bir komplikasyon varsa, bunları en aza indirmek regex motorunun verimliliğini biraz artıracaktır.


1
Sed olarak bu olurdused -i '10000,$ s/old_text/new_text/g'
Dani_l

Güzel. Nasıl sedkarşılaştıracağımı bilmiyorum - Dosya boyutundan dolayı marjinal olarak daha hızlı olduğunu düşünüyorum, ancak fazla değil.
Sobrique

Perl'nin sed'den daha hızlı olduğunu varsayardım, ama sed biraz daha az şifrelidir veya daha ziyade başlangıçta bir öğrenme eğrisi gerektirir.
Dani_l,

1
Şimdi derdim, tersini bakın - sen (neredeyse) yazma olabilir sedde perl, ama ikincisi de çok komut ayrıntılı daha yazmanıza olanak tanır.
Sobrique

0

Eski ve yeni metinler aynı uzunluktaysa, dosyayı arayabilir ve dosyanın tamamını kopyalamak yerine yalnızca değiştirilen baytları yazabilirsiniz. Aksi takdirde, çok fazla veriyi hareket ettirmek zorunda kalırsınız.

Not: Bu zor ve özel kod yazmayı içerir.

C veya C ++ ile çalışıyorsanız fseek için man sayfasına veya arama ve sistem çağrıları için tercih ettiğiniz dil paketleyicilere bakın.

Yalnızca komut satırını kullanmakta ısrar ediyorsanız ve metnin bayt ofsetlerini alabilirseniz, yerine yazılan metni "dd" komutları ile yerine yazabilirsiniz.

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.