Иногда нужно делать парсинг тяжёлых csv документов. Можно попытаться выполнить подобную задачу средствами PHP. Но как поведёт себя скрипт, если csv - файл весит 100 Мб. Скрипт не отработает. Произойдёт ошибка. Возможно не хватит оперативной памяти сервера. В этом случае есть выход: нужно разделить один большой csv файл на несколько маленьких. Таким образом вы снизите нагрузку на сервер.
Предлагаю вам своё решение. Посмотрите на файл для парсинга. Я не стал делать его большим, но вы должны понимать, что размер файла может быть достаточно большим. Вся сложность в том, что нужно скопировать названия столбцов и несколько раз вставлять в маленькие файлы. Как только большой файл будет поделён на части, то необходимо вставить названия столбцов в самое начало маленьких файлов. Содержимое большого файла должно быть поделено на равные части и записано в маленькие файлы. В этом заключается вся трудность. Если в csv файле нет первой строки с названиями столбцов, то это не правильный по составу файл.
column1;column2;column3;column4;column5;column6;column7;column8
1text1;text1;text1;text1;text1;text1;text1;text1
2text1;text1;text1;text1;text1;text1;text1;text1
3text1;text1;text1;text1;text1;text1;text1;text1
4text1;text1;text1;text1;text1;text1;text1;text1
5text1;text1;text1;text1;text1;text1;text1;text1
6text1;text1;text1;text1;text1;text1;text1;text1
7text1;text1;text1;text1;text1;text1;text1;text1
8text1;text1;text1;text1;text1;text1;text1;text1
9text1;text1;text1;text1;text1;text1;text1;text1
10text1;text1;text1;text1;text1;text1;text1;text1
11text1;text1;text1;text1;text1;text1;text1;text1
12text1;text1;text1;text1;text1;text1;text1;text1
13text1;text1;text1;text1;text1;text1;text1;text1
Теперь рассмотрим сам скрипт sh для разделения csv файла на куски. Перед тем как запустить скрипт создайте папку parts для записи небольших файлов. Логика работы скрипта:
#!/bin/bash
#Егор Астапов 2017-11-27
#копируем название столбцов + копирование файла без названия столбцов
sed '1,1d' file1.txt > file2.txt
#очистка папки от старых файлов
rm -rf parts/*
header=$(sed -n '1p;1q' file1.txt)
num_rows=$(cat file2.txt | wc -l)
num_rows=$((num_rows - 1))
num_rows_new=3
cd ./parts
#разбиваем большой csv-файл на части
split -l $num_rows_new ../file2.txt
echo "названия столбцов: "$header
echo "Количество строк (всего): "$num_rows
echo "Количество строк в новом файле: "$num_rows_new
i=1
for file in $(ls)
do
sed -i -e "1 s/^/$header\n/;" $file;
#echo "$file";
echo $i": "$file" -> file$i.txt"
#переименование файла
mv $file "file$i.txt"
i=$(($i+1))
done
#вывод:
#названия столбцов: column1;column2;column3;column4;column5;column6;column7;column8
#Количество строк (всего): 12
#Количество строк в новом файле: 3
#1: xaa -> file1.txt
#2: xab -> file2.txt
#3: xac -> file3.txt
#4: xad -> file4.txt
#5: xae -> file5.txt
Обратите внимание на переменную num_rows_new. Документ будет разбит по количеству строк согласно переменной num_rows_new. В итоге у вас будут масса файлов с одинаковым количеством строк, но последний файл будет отличаться от всех остальных. В нём будет наименьшее количество строк по остаточному принципу: 3 + 3 + 3 + 3 + 1 = 13. В последнем документе будет всего 2 строки. Одна с названиями столбцов, другая с данными. Вы можете не переименовывать файлы. В этом случае получится масса файлов с непонятными названиями: xaa, xab. Я советую вам переименовывать файлы. Так порядка больше. В итоге у вас получится несколько файлов. Я выводу содержимое всех файлов без разрывов.
cat parts/*
#вывод:
#column1;column2;column3;column4;column5;column6;column7;column8
#1text1;text1;text1;text1;text1;text1;text1;text1
#2text1;text1;text1;text1;text1;text1;text1;text1
#3text1;text1;text1;text1;text1;text1;text1;text1
#column1;column2;column3;column4;column5;column6;column7;column8
#4text1;text1;text1;text1;text1;text1;text1;text1
#5text1;text1;text1;text1;text1;text1;text1;text1
#6text1;text1;text1;text1;text1;text1;text1;text1
#column1;column2;column3;column4;column5;column6;column7;column8
#7text1;text1;text1;text1;text1;text1;text1;text1
#8text1;text1;text1;text1;text1;text1;text1;text1
#9text1;text1;text1;text1;text1;text1;text1;text1
#column1;column2;column3;column4;column5;column6;column7;column8
#10text1;text1;text1;text1;text1;text1;text1;text1
#11text1;text1;text1;text1;text1;text1;text1;text1
#12text1;text1;text1;text1;text1;text1;text1;text1
#column1;column2;column3;column4;column5;column6;column7;column8
#13text1;text1;text1;text1;text1;text1;text1;text1
Я для примера использовал файл с 13 строками (данные). Вы можете сделать большой файл на несколько мегабайт и разделить его на несколько скриптов.