Jak podzielić pliki CSV według określonej liczby wierszy?

84

Mam plik CSV (około 10000 wierszy; każdy wiersz ma 300 kolumn) przechowywany na serwerze LINUX. Chcę podzielić ten plik CSV na 500 plików CSV po 20 rekordów każdy. (Każdy ma taki sam nagłówek CSV, jak obecny w oryginalnym CSV)

Czy jest jakieś polecenie Linuksa, które pomoże w tej konwersji?

Pawan Mude
źródło
1
To rzeczywiście działa, jednak nagłówek pierwszego pliku zostanie zduplikowany, dając w ten sposób pierwsze nagłówki pliku csv 2.
rickman

Odpowiedzi:

79

Uczynił to funkcją. Możesz teraz zadzwonićsplitCsv <Filename> [chunkSize]

splitCsv() {
    HEADER=$(head -1 $1)
    if [ -n "$2" ]; then
        CHUNK=$2
    else 
        CHUNK=1000
    fi
    tail -n +2 $1 | split -l $CHUNK - $1_split_
    for i in $1_split_*; do
        sed -i -e "1i$HEADER" "$i"
    done
}

Znalezione na: http://edmondscommerce.github.io/linux/linux-split-file-eg-csv-and-keep-header-row.html

Martin Dinov
źródło
1
Czy możesz wyjaśnić, jak to działa? Sprawdziłem oryginalny post, ale nie ma też wyjaśnienia, ani nawet opcji umieszczania komentarzy.
shashi009
6
co się stanie, jeśli komórka w pliku CSV zawiera znak nowej linii?
Ondřej Hlaváček
Co to za znak nowej linii? Nadal działa dla mnie na UTF-8, nie jestem pewien, czy to pomaga.
owyongsk
3
@ shashi009: Załóżmy, że oryginalny plik nazywa się plik.txt. 1: pomiń pierwszą linię, a następnie potokuj resztę pliku split, który dzieli się na nowe pliki co 20 linii, z prefiksem split_2: iteruj przez nowe pliki split_ *, zapisując każdą nazwę do zmiennej file, pojedynczo 3: dla każdego ... 4: zapisz pierwszą linię (nagłówki kolumn) z naszego oryginalnego pliku do tmp_file 5: tmp_file dołącz plik podzielony na 20 linii do 6: nadpisz stary plik split_ * nowym tmp_file, aby zachować nagłówki kolumn
David,
1
Wstawianie nagłówka za pomocą echo -e "$HEADER\n$(cat $i)" > $ijest niepotrzebnie niepotrzebne. Zastąpiłem go sed -i -e "1i$HEADER" "$i".
Philipp Moers
150

Użyj polecenia podziału systemu Linux:

split -l 20 file.txt new    

Podziel plik „plik.txt” na pliki zaczynające się od nazwy „nowy”, każdy zawierający 20 linii tekstu.

Wpisz man splitpo znaku zachęty Unix, aby uzyskać więcej informacji. Będziesz jednak musiał najpierw usunąć nagłówek z pliku.txt (używając tailna przykład polecenia), a następnie dodać go z powrotem do każdego z podzielonych plików.

James King
źródło
Jak mogę pominąć pierwszy wiersz file.txt (nagłówek)?
forkfork
użyj, wc -laby uzyskać liczbę wierszy, a następnie weź tę wartość odejmij 1 (załóżmy, że wc -ldało to 50), a następnie uruchom tail -n 49(w tym przykładzie), aby uzyskać wszystko oprócz wiersza nagłówka. Zwróć uwagę, że wc -lliczy znaki <newline>, więc jeśli ostatnia linia nie kończy się znakiem nowej linii, liczba linii zostanie zmniejszona o 1.
Lucas Roberts,
4
@lucas tail -n +2 wypisze wszystkie wiersze oprócz pierwszej.
James King
@JamesKing, +1 i dzięki! Powinienem uważniej przeczytać dokumentację :)
Lucas Roberts
6
aby zachować „.csv” w nowych plikach, po prostu dodaj--additional-suffix=.csv
Cocuba
22

To powinno działać !!!

file_name= Nazwa pliku, który chcesz podzielić.
10000= Liczba wierszy, które każdy podzielony plik będzie zawierał
file_part_= Prefiks nazwy podzielonego pliku (file_part_0, file_part_1, file_part_2..etc tak dalej)

split -d -l 10000 nazwa_pliku.csv file_part_

Koral
źródło
to działa absolutnie dobrze! Czy istnieje sposób na ograniczenie liczby tworzonych przeze mnie plików wierszy o wartości 10000? Powiedzmy, że chcę, aby pierwsze 200 000 wierszy zostało podzielonych na 10 000 plików csv, a resztę zignorować.
Pronomita Dey
1
@Pronomitahead -200000 file.csv | split -l 10000 - new_
boloyao
2
Miałem plik CSV 13 Gb z uszkodzoną linią w wierszu około 69 000 000. Blokował import do bigQuery. Pozwoliło mi to na dzielenie go rekurencyjnie, aż mogłem wyodrębnić linię i ją naprawić. Żadne inne rozwiązanie nie było tak wydajne w obsłudze dużych plików bez wyłączania serwera lub blokowania rzeczy. Podzielenie pliku na 5 000 000 fragmentów wiersza zajęło około 2 minut. Dzięki!
LP Papillon
13

To powinno zrobić to za Ciebie - wszystkie Twoje pliki zostaną nazwane Part1-Part500.

#!/bin/bash
FILENAME=10000.csv
HDR=$(head -1 $FILENAME)   # Pick up CSV header line to apply to each file
split -l 20 $FILENAME xyz  # Split the file into chunks of 20 lines each
n=1
for f in xyz*              # Go through all newly created chunks
do
   echo $HDR > Part${n}    # Write out header to new file called "Part(n)"
   cat $f >> Part${n}      # Add in the 20 lines from the "split" command
   rm $f                   # Remove temporary file
   ((n++))                 # Increment name of output part
done
Mark Setchell
źródło
Stworzyło to pliki, ale tabulatory (mam na myśli \ t) zostały zastąpione spacjami, a moje pliki CSV używały \ t jako separatora
AmineG,
Można to nieco poprawić, uzupełniając liczby, tak aby pliki były wyświetlane po kolei automatycznie. Zamieniając $ {n} na $ (printf "% 05d \ n" $ n)
Phineas Dashevsky,
4
Linia nagłówka jest zduplikowana w pierwszym pliku.
Juha Palomäki