Yalnızca birkaç satırda değiştirilen bir dize gerektiren 25 GB metin dosyasına sahibim. sed
Baş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ı?
Yalnızca birkaç satırda değiştirilen bir dize gerektiren 25 GB metin dosyasına sahibim. sed
Baş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ı?
Yanıtlar:
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
sed
yanlış yazılmış. Bu yazıyı, dün sed
olması time sed -i '/original/ s//ketan/g' wiki10gb
gerekmeyen 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 sed
alternatif arasında bir fark görmedim. Zamandaki farkın yanlış yazımdan kaynaklandığından şüpheleniyorum.
time
Sonuçlarda kişisel olarak çok fazla dalgalanma gördüm , ancak sonuçta, zaman içinde hiçbir fark yoktu.
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 sed
ayrı 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 sed
ama 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.
sed -i '10000,$ s/old_text/new_text/g'
sed
karşılaştıracağımı bilmiyorum - Dosya boyutundan dolayı marjinal olarak daha hızlı olduğunu düşünüyorum, ancak fazla değil.
sed
de perl
, ama ikincisi de çok komut ayrıntılı daha yazmanıza olanak tanır.
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.