У меня есть CSV-файл, который выглядит следующим образом:
1,'someval','otherval',,,,,
'','someotherval','some_otherval',,,,,
1BSD,'',,,,,
2,'val',,,,,
,,,,,,
2BSD,,,,,,
2BCD,,,,,,
Теперь я хочу разбить файл, когда первый столбец новой строки является целочисленным значением.
Итак, тогда для вышеуказанного ввода CSV < Я должен получить 2 новых файла с содержанием:
1,'someval','otherval',,,,,
,'someotherval','some_otherval',,,,,
1BSD,'val',,,,,
и
2,'val',,,,,
,,,,,,
2BSD,,,,,,
2BCD,,,,,,
соответственно.
Как я могу сделать это, используя Bash и / или Python? Благодаря.
Вы можете использовать утилиту csplit
для разбиения регулярного выражения, например,
csplit -z file.csv '/^[0-9]\+,/' '{*}'
80
42
(значения показывают количество символов, выводимых в каждый файл - вы можете подавить их, добавив опцию -s
).
Выходные файлы по умолчанию называются xx00
, xx01
и т. Д. - при желании можно изменить префикс и суффикс.
Пример.
$ csplit -z file.csv '/^[0-9]\+,/' '{*}'
80
42
$ head xx*
==> xx00 <==
1,'someval','otherval',,,,,
'','someotherval','some_otherval',,,,,
1BSD,'',,,,,
==> xx01 <==
2,'val',,,,,
,,,,,,
2BSD,,,,,,
2BCD,,,,,,
Я хотел посмотреть, как много из этого я смогу сделать с sed
, и мне удалось сделать довольно многое из этого. Мы можем писать файлы с помощью sed
, используя команды w
и W
, но я не мог придумать, как написать отдельный файл для каждой итерации цикла sed
, поэтому мне пришлось использовать оболочку петля. sed
, вероятно, не тот инструмент, который можно использовать для этой работы, и, вероятно, есть более хороший способ сделать это с sed
. Во всяком случае, вот что я придумал:
#!/bin/bash
sed ':a;N;s/\n/\x00/; ta' input | sed -r 's/\x00([0-9]+(,|\x00|$))/\n\1/g' > edited
n=0
while [ -s edited ]; do
((n++))
sed -n '1p' edited > csv-"$n"
sed -i '1d' edited
done
sed -i 'y/\x00/\n/' csv-*
rm edited
заменяют символы новой строки нулевым символом \x00
, используя цикл sed
. Это сделано для того, чтобы позже мы могли использовать переводы строк как значимые разделители.
sed ':a;N;s/\n/\x00/; ta' input
передают результат и добавляют новые строки перед целыми числами, которые были в первом поле, и записывают результат в файл, edited
| sed -r 's/\x00([0-9]+(,|\x00|$))/\n\1/g' > edited
инициализировать переменную для увеличения
n=0
, пока edited
не пусто, делать вещи
while [ -s edited ]; do
инкремент n
((n++))
записать первую строку edited
в новый файл csv-$n
, где $n
- текущее значение n
sed -n '1p' edited > csv-"$n"
удалить первую строку из edited
sed -i '1d' edited
, это конец цикла, и поскольку у нас есть только одна строка для каждого файла, который мы хотим записать, это не так медленно, как обработка каждой строки исходного файла в цикле, но, тем не менее, это медленно!
для каждого файла, который мы создали, превратите нулевые символы обратно в символы новой строки
sed -i 'y/\x00/\n/' csv-*
удалить промежуточный файл
rm edited