Как разбить файлы CSV по количеству указанных строк?


84

У меня есть файл CSV (около 10 000 строк; каждая строка имеет 300 столбцов), хранящиеся на сервере LINUX. Я хочу разбить этот CSV-файл на 500 CSV-файлов по 20 записей в каждом. (У каждого из них тот же заголовок CSV, что и в исходном CSV)

Есть ли какая-нибудь команда Linux для помощи в этом преобразовании?


1
Это действительно работает, однако заголовок первого файла будет продублирован, что даст первому файлу csv 2 заголовка.
rickman


Ответы:


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".
Филипп Моерс

150

Используйте команду разделения Linux:

split -l 20 file.txt new    

Разделите файл «file.txt» на файлы, начинающиеся с имени «новый», каждый из которых содержит 20 строк текста.

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


Как я могу пропустить первую строку (заголовок) file.txt?
forkfork

используйте, wc -lчтобы получить количество строк, затем возьмите это значение, вычтите 1 (предположим, получилось wc -l50) и затем запустите tail -n 49(в этом примере), чтобы получить все, кроме строки заголовка. Обратите внимание, что wc -lучитываются символы <newline>, поэтому, если последняя строка не заканчивается символом новой строки, вы будете отключены на 1 в вашем количестве строк.
Лукас Робертс

4
@lucas, tail -n +2 напечатает все строки, кроме первой.
Джеймс Кинг,

@JamesKing, +1 и спасибо! Я должен прочитать документацию более внимательно :)
Лукас Робертс

6
для сохранения ".csv" в новых файлах просто добавьте--additional-suffix=.csv
Cocuba

22

Это должно работать !!!

file_name= Имя файла, который вы хотите разделить.
10000= Количество строк, которые должен содержать каждый разделенный файл
file_part_= Префикс имени разделенного файла (file_part_0, file_part_1, file_part_2..etc)

split -d -l 10000 имя_файла.csv часть_файла


это работает абсолютно нормально! Есть ли способ ограничить количество создаваемых мной файлов строк в 10000? Скажем, я просто хочу, чтобы первые 200000 строк были разделены на файлы csv по 10 тыс. Строк, а остальные игнорировались.
Pronomita Dey

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

2
У меня был файл CSV размером 13 ГБ с поврежденной строкой примерно в строке ~ 69 000 000. Он блокировал импорт в bigquery. Это позволило мне рекурсивно разделить его, пока я не смог изолировать строку и исправить ее. Ни одно другое решение не было столь эффективным в обработке больших файлов без остановки сервера или блокировки. На разбиение файла на 5 000 000 строк потребовалось около 2 минут. Благодаря!
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
Строка заголовка дублируется в первом файле.
Juha Palomäki

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.