Як розділити файли CSV за вказаною кількістю рядків?


83

Я маю файл CSV (близько 10000 рядків; кожен рядок має 300 стовпців), який зберігається на сервері LINUX. Я хочу розбити цей файл CSV на 500 файлів CSV по 20 записів кожен. (Кожен має такий самий заголовок CSV, який присутній в оригінальному CSV)

Чи існує якась команда Linux, яка допоможе здійснити це перетворення?


1
Це справді працює, однак, заголовок першого файлу буде продубльований, що дасть першому файлу csv 2 заголовки.
Рікман,


Відповіді:


79

Зробив це у функцію. Тепер ви можете зателефонувати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
}

Знайдено на: http://edmondscommerce.github.io/linux/linux-split-file-eg-csv-and-keep-header-row.html


1
Ви можете пояснити, як це працює? Я перевірив оригінальний пост, але також немає пояснення і навіть немає можливості розміщувати коментарі.
shashi009

6
що якщо клітинка в CSV містить новий рядок?
Ondřej Hlaváček

Що це за символ нового рядка? Це все ще працює для мене на UTF-8, не впевнений, чи допомагає це.
owyongsk

3
@ shashi009: Припустимо, що оригінальний файл називається file.txt. 1: пропустіть перший рядок, а потім перекладіть решту файлу split, який розділяється на нові файли довжиною кожні 20 рядків, з префіксом split_2: перебирайте нові файли split_ *, зберігаючи кожне ім'я до змінної file, по одному 3: для кожного ... 4: запишіть перший рядок (заголовки стовпців) з нашого вихідного файлу в tmp_file 5: додайте 20-рядковий файл розділення до tmp_file 6: перезапишіть старий файл split_ * новим tmp_file, щоб він зберігав заголовки стовпців
Девід

1
Попереднє попереднє оформлення заголовка через echo -e "$HEADER\n$(cat $i)" > $iнепотрібне значення. Я замінив його на sed -i -e "1i$HEADER" "$i".
Філіп Моерс

146

Використовуйте команду Linux split:

split -l 20 file.txt new    

Розділіть файл "file.txt" на файли, що починаються з назви "новий", кожен з яких містить по 20 рядків тексту.

man splitДля отримання додаткової інформації введіть у запиті Unix. Однак вам доведеться спочатку видалити заголовок із файлу file.txt (наприклад, за допомогою tailкоманди), а потім знову додати його до кожного з розділених файлів.


Як я можу пропустити перший (заголовковий) рядок file.txt?
виделка

використовуйте, wc -lщоб отримати кількість рядків, потім візьміть це значення, віднявши 1 (припустимо, це wc -lдало 50), а потім запустіть tail -n 49(у цьому прикладі), щоб отримати все, крім рядка заголовка. Зверніть увагу, що wc -lпідраховується <newline> символів, тому, якщо останній рядок не закінчується символом нового рядка, вам буде відключено 1 на вашу кількість рядків.
Лукас Робертс,

4
@lucas, tail -n +2 надрукує всі рядки, крім першого.
Джеймс Кінг,

@JamesKing, +1 та Дякую! Мені слід уважніше прочитати документи :)
Лукас Робертс

6
для збереження ".csv" у нових файлах просто додайте--additional-suffix=.csv
Кокуба,

22

Це має спрацювати !!!

file_name= Назва файлу, який потрібно розділити.
10000= Кількість рядків, які міститиме кожен розділений файл
file_part_= Префікс імені розділеного файлу (file_part_0, file_part_1, file_part_2 ... тощо)

розділити -d -l 10000 ім'я_файла.csv файл_част_


це працює абсолютно добре! Чи можу я обмежити кількість 10000 файлів рядків, які я створюю? Скажімо, я просто хочу, щоб перші 200 000 рядків були розділені на CSV-файли 10 тис. Рядків, а решту проігнорувати.
Pronomita Dey

1
@Pronomitahead -200000 file.csv | split -l 10000 - new_
boloyao

2
У мене був файл CSV розміром 13 Гб із пошкодженим рядком приблизно в рядку ~ 69 000 000. Він блокував імпорт у bigquery. Це дозволило мені розділити його рекурсивно, поки я не зміг ізолювати лінію та виправити її. Жодне інше рішення не було настільки ефективним у обробці великих файлів, не приводячи сервер до ладу або не блокуючи речі. Потрібно близько 2 хвилин, щоб розділити файл на 5 000 000 шматочків рядків. Дякую!
LP Papillon

13

Це має зробити це за вас - усі ваші файли в кінцевому підсумку називатимуться 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

Це створило файли, але вкладки (я маю на увазі \ t) були замінені пробілами, а мої файли CSV використовували \ t як роздільник
AmineG,

Це можна трохи покращити, заповнивши цифри, щоб файли автоматично відображалися послідовно. Замінивши $ {n} на $ (printf "% 05d \ n" $ n)
Фінеас Дашевський

4
Рядок заголовка дублюється в першому файлі.
Юха Паломякі,

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.