Регулярное выражение для разбора CSV
foreach (@fields) {
s/\\\\/\\/g;
s/\\;/;/g;
}
Может кто-нибудь может предложить более "умный" сабж.
Нужно разбивать строку на "слова". Разделителем является ";". Для того чтоб использовать ";" в тексте ее необходимо экранировать символом "\", а для того чтоб использовать "\" его необходимо экранировать собой.
Создаю вторую тему, которая хоть немного отдалена от правящего здесь примитива, и ни одного ответа. Неужели никому не интересно обсуждать что-то, кроме модуля CGI и сложения чисел?
Во-первых, ((?:\\.|[^;])+) вместо ((?:\\.|[^;])*), во-вторых я не сказал о недостатках данного РВ. Исправляюсь: со строками типа:
f1;f2\;;\\f3\\\;ff;
все работает отлично, а вот с таким (содержащими пустые поля):
f1;;f3;;f5;
нумерация полей в массиве сбивается.
CSV твой или чужой (всмысле можеш ли изменять формат выдачи данных и принцип защиты спец символов?)
Цитата:
Originally posted by Alone
CSV твой или чужой (всмысле можеш ли изменять формат выдачи данных и принцип защиты спец символов?)
CSV твой или чужой (всмысле можеш ли изменять формат выдачи данных и принцип защиты спец символов?)
Описанный мной принцип защиты спец символов является стандартным (почти=).
К тому же, такая задача встречается довольно часто.
Код:
use strict;
my $v = '"aa\\";a\\\\";e;1;;m;9.2;';
my @a;
while ($v =~ /"([^"\\]*(\\.[^"\\]*)*)";?|([^;]+);?|;/g) {
push (@a, defined($1) ? $1 : $3);
}
push (@a, undef) if $v =~ /;$/;
print @a+0,"\n";
print "@a";
my $v = '"aa\\";a\\\\";e;1;;m;9.2;';
my @a;
while ($v =~ /"([^"\\]*(\\.[^"\\]*)*)";?|([^;]+);?|;/g) {
push (@a, defined($1) ? $1 : $3);
}
push (@a, undef) if $v =~ /;$/;
print @a+0,"\n";
print "@a";
Цитата:
Originally posted by 2NetFly
Подсказали мне рабочее решение. Принцип защиты спец. символов соответствует описанному выше, но дополнительно нужна брать в кавычки все строки. Решение принадлежит Фридлу.
Подсказали мне рабочее решение. Принцип защиты спец. символов соответствует описанному выше, но дополнительно нужна брать в кавычки все строки. Решение принадлежит Фридлу.
Код:
use strict;
my $v = '"aa\\";a\\\\";e;1;;m;9.2;';
my @a;
while ($v =~ /"([^"\\]*(\\.[^"\\]*)*)";?|([^;]+);?|;/g) {
push (@a, defined($1) ? $1 : $3);
}
push (@a, undef) if $v =~ /;$/;
print @a+0,"\n";
print "@a";
my $v = '"aa\\";a\\\\";e;1;;m;9.2;';
my @a;
while ($v =~ /"([^"\\]*(\\.[^"\\]*)*)";?|([^;]+);?|;/g) {
push (@a, defined($1) ? $1 : $3);
}
push (@a, undef) if $v =~ /;$/;
print @a+0,"\n";
print "@a";
Давно я perlom занимался, поэтому ничего не понял, что написано. Но на вопрос постараюсь ответить.
Я думаю, самый простой способ - это сначало убрать из строки все лищние точки с запятой, - "/;", заменив их, скажем, на "&#номер_точки_с_запятой" и двойные слэши, заменив их на одинарные, а затем разбить строчку БЕЗ спец.символов на слова.
Потом в каждом слове, если нужно, все поменять обратно.
f1\\;f2
"\" экранируется собой, не отменяя действия разделителя, а предложенный тобой алгоритм этого не заметит.
ЗЫ Тут язык, собственно, значения не имеет. Важно регулярное выражение (лучше, использующее механизм НКА).
По поводу темы.
Если тебе нужно распарзить строку, то есть такой модуль. Находиться здесь
http://search.cpan.org/author/JWIED/Text-CSV_XS-0.23/CSV_XS.pm
Если, ты придумал регулярку можешь кинуть ее сюда.