Perl Regex: как удалить кавычки внутри кавычек из строки CSV

У меня есть строка из CSV-файла с " в качестве ограничителя полей и , в качестве разделителя полей в виде строки. Иногда в данных есть ", которые нарушают ограничители поля. Я ищу регулярное выражение для удаления этих ".

Моя строка выглядит так:

my $csv = qq~"123456","024003","Stuff","","28" stuff with more stuff","2"," 1.99 ","",""~;

Я просмотрел это, но не понимаю, как сказать, чтобы он удалял только цитаты, которые

  1. не в начале строки
  2. не в конце строки
  3. без предшествующего ,
  4. за которым не следует ,

Мне удалось сказать ему удалить 3 и 4 одновременно с этой строкой кода:

$csv =~ s/(?<!,)"(?!,)//g;

Однако я не могу поместить туда ^ и $, так как оба вида вперед и назад не любят писаться как (?<!(^|,)).

Есть ли способ добиться этого только с помощью регулярного выражения, помимо разделения строки и удаления кавычек из каждого элемента?


person simbabque    schedule 04.05.2012    source источник
comment
Есть два типа регулярных выражений CSV: те, которые не работают сейчас, и те, которые не будут работать.   -  person brian d foy    schedule 04.05.2012


Ответы (5)


Это должно работать:

$csv =~ s/(?<=[^,])"(?=[^,])//g

1 и 2 подразумевают, что должен быть хотя бы один символ до и после запятой, отсюда и положительный поиск. 3 и 4 подразумевают, что эти символы могут быть чем угодно, кроме запятой.

person flesk    schedule 04.05.2012
comment
Вы, сэр, гений. :D Спасибо. - person simbabque; 04.05.2012
comment
Это также удалит конечную кавычку. т.е. abc,def становится abc,def. Поэтому я добавил, за которым не следует новая строка 's/(?‹=[^,])(?=[^,)])(?!$)//g' - person Interlated; 12.11.2015

Для управления данными CSV я бы рекомендовал использовать Text::CSV. - в данных CSV есть много потенциальных сложностей, которые, хотя и можно создать код для обработки самостоятельно, не стоят усилий, когда есть испытанный и протестированный модуль CPAN, который сделает это за вас.

person beresfordt    schedule 04.05.2012
comment
Я знаю, но я хочу только убрать кавычки, я больше ничего не делаю с данными. Это скорее общий вопрос о том, как работает обходной путь. - person simbabque; 04.05.2012
comment
Если вы не рассматриваете это исключительно как упражнение по обучению регулярному выражению, в какой-то момент вас укусит неожиданное форматирование (т.е. не обработанное вашим регулярным выражением) в данных CSV. Я сам проигнорировал этот совет и научился на собственном горьком опыте! - person beresfordt; 04.05.2012

Не используйте Regex для анализа CSV-файла, CPAN предоставляет множество хороших модулей, например, как предлагает nickifat, используйте Text::CSV или вы можете использовать Text::ParseWords как

use Text::ParseWords;  
while (<DATA>) {
chomp;     
my @f = quotewords ',', 0, $_;     
print join "|" => @f; 
}  

__DATA__ 
"123456","024003","Stuff","",""28" stuff with more stuff","2"," 1.99 ","","" 

Выход:

123456|024003|Stuff||28 stuff with more stuff|2| 1.99 || 
person Nikhil Jain    schedule 04.05.2012
comment
Спасибо за ваш вклад. Я не знал о Text::ParseWords, и это выглядит полезным. Но опять же, я не собираюсь использовать данные из CSV-файла. Я только хотел удалить кавычки внутри текста. Я не создаю CSV и не читаю его. Я просто очищаю данные, которые уже выглядят как файл CSV и куда-то уходят. - person simbabque; 04.05.2012

Спасибо за помощь здесь. У меня были проблемы с плохо отформатированным CSV со встроенными двойными кавычками. Я бы сделал одно небольшое дополнение к упреждающей части регулярного выражения, иначе нулевые значения в конце строки будут повреждены:

(?<=[^,])\"(?=[^,\n])

Добавление \n устранит совпадение с последней двойной кавычкой в ​​конце строки.

person BRUCE A FOLEY    schedule 14.11.2013

предложенный

$csv =~ s/(?<=[^,])"(?=[^,])//g;

вероятно, лучший ответ. Без этих расширенных функций регулярных выражений вы могли бы сделать то же самое с

$csv =~ s/([^,])"([^,])/$1$2/g;

or

$csv = join (',', map {s/"//g;"\"$_\""} split (',', $csv));

Я думаю, вы должны знать, что ваша строка неправильно отформатирована в формате csv. В файле csv двойные кавычки внутри значений должны быть удвоены (http://en.wikipedia.org/wiki/Comma-separated_values). В вашем формате значения не могут содержать кавычки рядом с запятыми.

csv не такой простой формат. Если вы решите использовать «настоящий» csv, вам следует использовать модуль. В противном случае вам, вероятно, следует удалить все двойные кавычки, чтобы упростить код и уточнить, что вы не делаете csv.

person webreac    schedule 04.05.2012
comment
Они разные. # 2 не обрабатывает две кавычки подряд. #3 еще хуже, разделив поля запятыми на два. - person ikegami; 04.05.2012