Анализ данных, разделенных запятыми
Проблема
Имеется файл данных, поля которого разделены запятыми. Однако в полях могут присутствовать
свои запятые (находящиеся внутри строк или снабженные служебными префиксами). Многие электронные
таблицы и программы для работы базами данных поддерживают списки полей, разделенных запятыми,
в качестве стандартного формата для обмена данными.
Решение
Воспользуйтесь следующей процедурой:
sub parse_csv {
my $text = shift; # Запись со значениями, разделенными запятыми
my @new = ():
push(@new, $+) while $text =~ m {
# Первая часть группирует фразу в кавычках
"([^\"\\]*(?:\\.[^\"\\]*)*)",?
| ([^,]+),?
| ,
}gx;
push(@new, undef) if substr($text, -1,1) eq ',';
return @new; #Список значений, которые разделялись запятыми
}
Также можно воспользоваться стандартным модулем Text.ParseWords:
use Text::ParseWords;
sub parse_csv {
return quoteword(",",0, $_[0]);
}
Комментарий
Ввод данных, разделенных запятыми, — коварная и непростая задача. Все выглядит просто,
но в действительности приходится использовать довольно сложную систему служебных символов,
поскольку сами поля могут содержать внутренние занятые. В результате подстановка получается
весьма сложной, а простая функция
split /, / вообще исключается.
К счастью, модуль Text::ParseWords скрывает от вас все сложности. Передайте функции
qoutewords два аргумента и строку разделенных данных. Первый аргумент определяет
символ-разделитель (в данном случае — запятая), а второй — логический флаг, который показывает,
должна ли возвращаемая строка содержать внутренние кавычки.
Если кавычки должны присутствовать внутри поля, также ограниченного кавычками,
воспользуйтесь префиксом \: "like \"this\". Кавычки, апострофы и обратная косая черта —
единственные символы, для которых этот префикс имеет специальное значение. Все остальные
экземпляры \ остаются в итоговой строке.
Ниже показан пример использования процедуры parse_csv. q<> — всего лишь хитроумный
заменитель кавычек, благодаря которому нам не придется расставлять повсюду символы \.
$line = q<XYZZY, "", "0'Reilly, Inc", "Wall, Larry", "a\"glag\"bit," 5,
"Error. Core Dumped">;
@fields = parse_csv($line);
for ($i = 0; $i < @fields; $i++) {
print "$i : $fields[$i]\n";
}
0 : XYZZY
1 :
2 : O'Reilly, Inc
3 : Wall, Larry
4 : a \"glug\" bit,
5 : 5
6 : Error, Core Dumped
См. также
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|