Büyük bir CSV dosyasını yeniden dizine ekleme


11

Bu yararlı iş parçacığında cevaplar geçti , ama benim sorunum (en azından ile sed) iyi cevap düşünemiyorum yeterince farklı görünüyor .

Aşağıdaki gibi görünen satırları ile büyük bir CSV dosyası (200+ GB) var:

<alphanumerical_identifier>,<number>

Burada <alphanumerical_identifier>tüm dosyada benzersizdir. İlk sütunu bir dizinle değiştiren ayrı bir dosya oluşturmak istiyorum , yani

<index>,<number>

böylece:

1, <number>
2, <number>
3, <number>

Can awkbellekte tam dosyayı yüklemeden artan endeks oluşturmak?

Endeks monoton olarak arttığından, sadece indeksi bırakmak daha iyi olabilir. Bunun çözümü bu kadar farklı olabilir mi?

<number>
<number>
<number>

Bu çözümün fizibilitesinden emin değilim. Ancak, ayrı bir dosyada CSV dosyasındaki kadar sayı üretmeye ve ardından CSV dosyasının ikinci sütununu bu dosyaya eklemeye ne dersiniz?
Ramesh

@Ramesh Çıktı doğru olduğu sürece bu gayet iyi.
Amelio Vazquez-Reina

2
Bir şeyi yanlış anladığımı sanıyorum; aksi takdirde awk -F, '{print ++n, $2}'çalışır. Veya awk -F, '{print $2}'ikinci varyasyon için.
G-Man, 'Monica'yı Eski

2
@ G-Man, muhtemelen bu kadar FNRiyi hizmet ++n
vermesine

1
Bu Uniq Identifier'dan gerçekten kurtulabileceğinizi üç kez kontrol ediyorum ... neden indeksle bir ilk (3.) sütun eklemiyorsunuz, ancak yine de tanımlayıcıyı koruyorsunuz? bu tanımlayıcı başka hiçbir yerde kullanılmıyor mu?
Olivier Dulac

Yanıtlar:


13

Test etmek için bir terminalin yanında değil, ama genellikle göz ardı edilen nlkomuta ne dersiniz ? Gibi bir şey:

cut -f 2 -d , original.csv | nl -w 1 -p -s , > numbered.csv


1
Not: 200 GB'lık bir CSV dosyası mı? Vay be, ve ben bir CSV (DVD birkaç) olarak Kuzey Amerika Ported Sayı Veritabanı ile çalışmak büyük olduğunu düşündüm!
bishop

1
Sayıdan sonra büyük bir boşluk olmasına rağmen çalışır. Ben onun yerine:cut -d, -f 2- /tmp/aa | nl -w 1 -p -s ,
Ángel

@Angel: Teşekkürler, cevabımı -w 1sol numaralandırma yerine genişlik seçeneğini kullanacak şekilde güncelledim .
bishop

Thanks @bishop - Girdi ve çıktı dosya adları nereye gidiyor?
Amelio Vazquez-Reina

1
@ user815423426 Evet, dikey çizgi cutsimgesinden ( |) önceki komut , etkin bir şekilde kapalı satır numaralarına sahip olan sadece ikinci sütunu verecektir.
bishop

7

İşte birkaç yaklaşım, ancak hiçbiri yukarıdaki çözümün cutve nlçözümün hızına yaklaşmayacak :

  1. awk

    awk -F, '{$1=NR;print $1","$2;}' file.csv > newfile.csv
  2. Perl

    perl -pe 's/[^,]+/$./' file.csv > newfile.csv

    veya

    perl -F, -ane '$F[0]=$.; print join ",", @F' file.csv
  3. Shell (ancak 200G dosyası için önermiyorum, yaşlanacaktır)

    i=1; while IFS=, read foo num; do 
            printf "%d,%s\n" $((i++)) $num; 
    done < file.csv > newfile.csv

Yukarıdaki çözümler hız sırasına göre sıralanmıştır. Dizüstü bilgisayarımda ve 40M dosyada test ettim ve kabuk (ortalama 10 çalıştırma) 2.2282 (awk), 2.4555 (1. perl), 3.1825s (2. perl) ve kabuk için 48.6035s aldılar. Çok zekicutnlZaten sahip olduğunuz ve çözüm, 0.6078'lerde yaklaşık 4 kat daha hızlıydı.


Güzel, istatistikler için teşekkürler! Kabuk sonucu beni biraz şaşırtıyor. Eğer değiştirirseniz printfile echo, zamanlama önemli ölçüde artırır?
piskopos

2
40G dosyası 2.2282 saniyede işlendi mi? Bana o dizüstü bilgisayarı nereden bulabilirim?
John B

2
@JohnB umm, evet, üzgünüm, G değil 40M idi :)
terdon

İle $1yaklaşımın sıfırlanmasını seviyorum awk. cutSolüsyon çok daha hızlı kesinlikle, ama yerine geçmez olarak bu beklenen bir <alphanumerical_identifier>şey ile. Ben en hızlı düşünmek awkvaryant gibi bir şey olabilir: mawk 'BEGIN{FS=OFS=","}{$1=NR}1' file.csv > newfile.csv.
John B

@JohnB ah, evet, OFSaçıkça yazdırmak yerine kullanmanın ,biraz daha hızlı olacağını ve bunun büyük dosyada önemli bir fark yaratabileceğini tahmin ediyorum.
terdon
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.