2008-10-08 3 views
0

Позвольте мне предисловие к этому, сказав, что я полный любитель, когда дело доходит до RegEx и только началось несколько дней назад. Я пытаюсь решить проблему форматирования файла и попал в зацепку с определенным типом данных. Входной файл структурирован следующим образом:Regex Partial String CSV Matching

 
Two words,Word,Word,Word,"Number, number" 

Что мне нужно сделать, это отформатировать его, как это ...

 
"Two words","Word",Word","Word","Number, number" 

Я имел RegEx образец

s/,/","/g

рабочий , за исключением того, что он также заменяет запятую в уже цитированном номере Number, number, который вызывает разделение поля и разбивает файл. По сути, мне нужно изменить свой шаблон, чтобы заменить запятую на «,» [цитату запятой цитаты], но только тогда, когда за этой запятой не следует пробел. Обратите внимание, что другие поля никогда не будут иметь пробела после запятой, а только список номеров с разделителями.

мне удалось подправить

s/,[A-Za-z0-9]/","/g

, которые, подбирая соответствующие строки, будет заменить запятой и следующее письмо. Я слышал об обратных ссылках и думаю, что это может быть то, что мне нужно использовать? Насколько я понимаю,

s/(,)[A-Za-z0-9]\b

должен работать, но это не так.

У кого-нибудь есть идея?

ответ

1

s/,([^ ])/","$1/ будет соответствовать «,», за которым следует «не-пробел», захватывая не-пространство, а затем заменяя все это на захваченную часть.

В зависимости от того, какой двигатель регулярного выражения вы используете, вы можете написать \1 или другие вещи, а не $1.

Если вы используете Perl или иным образом имеете доступ к движку регулярных выражений с отрицательным внешним видом, то s/,(?!)/","/,» не следует пробелом).

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

+0

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

+0

s /, (?!)/","/ Работал отлично, спасибо. Я использую Perl, поэтому я могу запустить скрипт против файлов, когда их отправят. Сохраняет его в Parser и работает с ним там. Кроме того, я хотел изучить Perl и RegEx так или иначе, чтобы две птицы с одним камнем. Спасибо за вашу помощь :). –

2

Моим опытом было то, что это не очень удобно использовать регулярные выражения. Как уже говорилось, файлы CSV лучше обрабатываются реальными синтаксическими анализаторами CSV. Вы не отметили язык, поэтому его трудно сказать, но в perl я использую Text :: CSV_XS или DBD :: CSV (позволяя мне SQL получить доступ к CSV-файлу, как если бы это была таблица, которая, конечно же, использует текст :: CSV_XS под обложками). Намного проще, чем катить мой собственный, и гораздо более надежный, чем использование регулярных выражений.

0

Этот вопрос похож на: Replace patterns that are inside delimiters using a regular expression call.

Это может работать:

s/"([^"]*)"|([^",]+)/"$1$2"/g 
+0

Хе-хе, который выполняет то, чего хочет Исаак, а не то, что он просил :) Вы могли бы стать немного фаворитом, а также избегать цитаты CSV ... но не так много смысла обрабатывать его регулярным выражением, когда готовые парсеры CSV могут сделать лучше. – ephemient

+0

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

0

Похоже, вы используете Sed.

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

через СЭД, ваша команда будет:

sed 's/[ \"]*,[ \"]*/\", \"/g' 

Обратите внимание, что вам все равно придется ставить doublequotes в начале и в конце строки.