В нашем проекте мы должны импортировать файл CSV в пост-ГРЭС. Существует несколько типов файлов, означающих длину изменений файла, как некоторые файлы с меньшим количеством столбцов и некоторыми со всеми ними.
Нам нужен быстрый способ импортировать этот файл в пост-ГРЭС. Я хочу использовать КОПИЮ С пост-ГРЭС, так как требование к скорости обработки очень высоко (почти 150 файлов в минуту с 20K размером файла каждый).
Так как числа столбцов файла не фиксируются, я должен предварительно обработать файл, прежде чем я передам его процедуре пост-ГРЭС. Предварительная обработка должна просто добавить дополнительные запятые в csv для столбцов, которые не находятся там в файле.
Существует две опции для меня предварительно обработать файл - Python использования или использовать Sed.
Мой первый вопрос, каков был бы самый быстрый способ, предварительно обрабатывают файл?
Второй вопрос, Если бы я использую sed, как я вставил бы запятую после того, как говорят 4-е, 5-е поля запятой?
например, если файл имеет записи как 1,23,56, мы, 89,2009-12-06, и я должен отредактировать файл с окончательным результатом как: 1,23,56, мы, 89, 06.12.2009
Известно ли вам, что КОПИРОВАТЬ ИЗ
позволяет указать, какие столбцы (а также в каком порядке) должны быть import?
COPY tablename ( column1, column2, ... ) FROM ...
Прямое указание на уровне Postgres столбцов для импорта и в каком порядке обычно является самым быстрым и эффективным методом импорта.
Как уже было сказано, существует гораздо более простой (и переносимый) способ использования sed
(чем то, что было представлено в других сообщениях) для замены n th вхождение , например замените 4-е и 5-е вхождения запятой на двойные:
echo '1,23,56,we,89,2009-12-06' | sed -e 's/,/,,/5;s/,/,,/4'
дает:
1,23,56,we,,89,,2009-12-06
Обратите внимание, что я сначала заменил крайние правые поля (# 5).
Я вижу, что вы также пометили свой вопрос как связанный с perl
, хотя вы не делаете явной ссылки на perl
в тексте вопроса; вот одна возможная реализация, которая дает вам гибкость также переупорядочивания или другой обработки полей:
echo '1,23,56,we,89,2009-12-06' |
perl -F/,/ -nae 'print "$F[0],$F[1],$F[2],$F[3],,$F[4],,$F[5]"'
также производит:
1,23,56,we,,89,,2009-12-06
Очень похоже на awk
, для записи:
echo '1,23,56,we,89,2009-12-06' |
awk -F, '{print $1","$2","$3","$4",,"$5",,"$6}'
Я оставлю Python кому-то другому.:)
Небольшое примечание к примеру Perl: я использую параметры -a
и -F
для автоматического разделения, поэтому у меня есть более короткая командная строка; однако при этом новая строка остается встроенной в последнее поле ( $ F [5]
), что нормально, если это поле не нужно переупорядочивать в другом месте. Если возникнет такая ситуация, потребуется немного больше ввода, чтобы вырезать новую строку с помощью chomp
, затем разделить
вручную и, наконец, напечатать наш собственный символ новой строки \ n
] (приведенный выше пример awk
не имеет этой проблемы):
perl -ne 'chomp;@F=split/,/;print "$F[0],$F[1],$F[2],$F[3],,$F[4],,$F[5]\n"'
COMMAS_TO_DOUBLE="1 4 5"
echo '1,23,56,we,89,2009-12-06' |
sed -e `for f in $COMMAS_TO_DOUBLE ; do echo "s/,/,,/$f" ; done |
sort -t/ -k4,4nr | paste -s -d ';'`
1,,23,56,we,,89,,2009-12-06
Извините, не смог устоять. :)
Чтобы ответить на ваш первый вопрос, sed
будет иметь меньше накладных расходов, но может быть болезненным. awk
было бы немного лучше (он более мощный). Perl или Python имеют больше накладных расходов, но с ними легче работать (что касается Perl, это, возможно, немного субъективно;). Лично я бы использовал Perl).
Что касается второго вопроса, я думаю, что проблема может быть немного сложнее. Например, разве вам не нужно исследовать строку, чтобы выяснить, какие поля на самом деле отсутствуют? Или гарантировано, что всегда будет 4-й и 5-й? Если это первый случай, было бы способом проще сделать это в Python или Perl, чем в sed
. В противном случае:
echo "1,23,56,we,89,2009-12-06" | sed -e 's/\([^,]\+\),\([^,]\+\),\([^,]\+\),\([^,]\+\),\([^,]\+\),/\1,\2,\3,\4,,\5,,/'
или (проще для глаз):
echo "1,23,56,we,89,2009-12-06" | sed -e 's/\(\([^,]\+,\)\{3\}\)\([^,]\+\),\([^,]\+\),/\1,\3,,\4,,/'
Это добавит запятую после 5-го и 4-го столбцов, если в тексте нет других запятых.
Или вы можете использовать два sed
для чего-то менее уродливого (хотя и немного):
echo "1,23,56,we,89,2009-12-06" | sed -e 's/\(\([^,]*,\)\{4\}\)/\1,/' | sed -e 's/\(\([^,]*,\)\{6\}\)/\1,/'
@OP, вы обрабатываете CSV-файл с отдельными полями и разделителями. Используйте инструмент, который может разделять разделители и предоставлять поля для удобной работы. sed не является одним из них, хотя это можно сделать, как предлагали некоторые из ответов, но вы получите регулярное выражение sed, которое трудно читать, когда оно усложняется. Используйте такие инструменты, как awk / Python / Perl, где они легко работают с полями и разделителями, лучше всего, доступны модули, специально предназначенные для обработки csv. Для вашего примера простой подход Python (без использования модуля csv, который в идеале вы должны попробовать его использовать)
for line in open("file"):
line=line.rstrip() #strip new lines
sline=line.split(",")
if len(sline) < 8: # you want exact 8 fields
sline.insert(4,"")
sline.insert(6,"")
line=','.join(sline)
print line
output
$ more file
1,23,56,we,89,2009-12-06
$ ./python.py
1,23,56,we,,89,,2009-12-06
sed 's/^([^,]*,){4}/&,/' <original.csv >output.csv
Добавляет запятую после 4-го поля, разделенного запятой (путем сопоставления 4 повторений
, а затем добавления запятой после этого). Обратите внимание, что здесь есть загвоздка; убедитесь, что ни одно из этих значений не является строкой в кавычках с запятыми.
Вы можете связать несколько замен через каналы, если это необходимо, или изменить регулярное выражение, чтобы добавить любые необходимые запятые одновременно (хотя это становится более сложным; вам нужно будет использовать захват подгрупп в вашем тексте замены).
Не знаю относительно скорости, но вот выражение sed, которое должен выполнить свою работу:
sed -i 's/\(\([^,]*,\)\{4\}\)/\1,/' file_name
Просто замените 4 желаемым количеством столбцов
В зависимости от ваших требований, рассмотрите возможность использования ETL программного обеспечения для этой и будущих задач. Такие инструменты, как Pentaho и Talend, предлагают большую гибкость, и вам не придется писать ни строчки кода.