2013-08-21 2 views
0

Итак, я хочу искать A, B, C, D в строке в любом порядке, но если C не существует, я все равно хочу, чтобы он дал мне A, B и D и т. Д.Может ли регулярные выражения искать группы независимо от порядка или все они существуют?

To более конкретно, вот точная проблема, которую я пытаюсь решить. CSV-файл с строками, которые выглядят так:

Name,(W)5555555,(H)5555555,(M)5555555,(P)5555555 

Однако W, H, M, P может быть в любом порядке. Плюс они не все существуют на каждой линии. Так это выглядит примерно так:

Name,(W)5555555,(H)5555555,(M)5555555,(P)5555555 
Name,(H)5555555,(P)5555555,(W)5555555,(M)5555555 
Name,(M)5555555,(H)5555555,, 
Name,(P)5555555,,, 

Что мне нужно выполнить, чтобы поместить все элементы в правильном порядке, чтобы они выстраиваются под правильными колоннами. Таким образом, выше должен выглядеть следующим образом, когда я сделал:

Name,(W)5555555,(H)5555555,(M)5555555,(P)5555555 
Name,(W)5555555,(H)5555555,(M)5555555,(P)5555555 
Name,,(H)5555555,(M)5555555, 
Name,,,,(P)5555555 

Edit: Оказывается я плохой Stack Overflow гражданин. Я не получал ответов достаточно быстро, когда мой проект нужно было сделать, и поэтому забыл вернуться и добавить правильные вопросы в свой пост. Я закончил писать сценарий python для этого, вместо того, чтобы просто использовать find/replace в BBEdit или Sublime Text 2, как я изначально пытался сделать.

Таким образом, мне нужен способ сделать что-то подобное, что работает либо в BBEdit, либо в Sublime Text. Или Вим, если на то пошло. На этот раз я постараюсь лучше взглянуть на него, и я отвечу на ответы, которые уже существуют.

+2

Чтобы процитировать описание тега 'regex': * Также укажите тег, определяющий язык программирования или инструмент, который вы используете. * –

+2

Было бы хорошо, если бы вы могли включить в свой вопрос язык, который вы используете, и ваши попытки (ы) до сих пор. – Jerry

+0

Безусловно выполнимо.Понятно, что вам нужно рассматривать каждый элемент как отдельный запрос, а затем хранить результаты в каком-либо структурированном объекте, будь то в базе данных или в массиве/списке/словаре/и т. Д. Затем вам нужно будет перезаписать CSV-файл. Я не уверен, что регулярные выражения - лучший инструмент для этой работы, если вы действительно не ищете * шаблоны * вместо конкретных разделителей, таких как 'W',' H', 'M' и т. Д. –

ответ

1

Если ваш аромат регулярного выражения поддерживает lookarounds, это можно сделать с помощью простого регулярного выражения. Так как lookaheads не продвигают позицию курсора двигателя регулярного выражения, мы можем использовать их для поиска нескольких шаблонов где-то после одной конкретной позиции. Мы можем зафиксировать все эти выводы и записать их обратно в заменяющую строку. Чтобы убедиться, что все они являются необязательными, мы могли бы просто использовать ?, но в этом случае я добавлю пустую альтернативу lookahead - это необходимо, чтобы обмануть движок, когда он возвращается обратно. Шаблон может выглядеть следующим образом:

^Name,(?=.*([(]W[)]\d+)|)(?=.*([(]H[)]\d+)|)(?=.*([(]M[)]\d+)|)(?=.*([(]P[)]\d+)|).* 

.* в конце, чтобы убедиться, что все становится удален в замене.

И строка замены, как это:

Name,$1,$2,$3,$4 

Here is a working demo используя ECMAScript аромат. Это довольно ограниченный вкус, поэтому это решение должно быть адаптировано к большинству сред.

+0

Кажется, это все находит и дает мне необходимые группы. Однако это не позволяет мне помещать их в правильном порядке (что не будет одинаковым для каждой строки, потому что это зависит от того, какой порядок они предназначены для каждой строки, что несовместимо. возможно, чтобы эти группы назывались группами вместо этого, чтобы их можно было разместить в определенном порядке? –

+0

На самом деле, я ошибаюсь. Кажется, что все это делается в правильном порядке. Теперь мне просто нужно рисовать (W) 5555555, (H) 5555555, (M) 5555555, (P) 5555555 Однословочное (, W) 5555555, (H) 5555555, (M) 5555555, (P) 5555555 Обратите внимание, что некоторые из них имеют quotati по меткам с запятой посередине, а некоторые нет. –

+0

Следующее дополнение к вашему регулярному выражению, похоже, работает в Sublime Text, хотя оно не работает на regexr.com: '^ (? (? = \". + \ ") (\". + \ ") | ([^,] +)), (= * ([(] W [)] \ d +?.) |) (? = * ([(] H [)] \ d +.) |?.) (= * ([(] M [)] \ d +) |) (? =. * ([(] P [)] \ d +) |). * ' Недостатком является то, что он рассматривает два разных параметра имени: $ 1 и $ 2, поэтому с заменой, как '$ 1, $ 2, $ 3, $ 4, $ 5, $ 6', имена формата' 'Last, First'' будут в конечном итоге в первом поле, но имена формата' singleword' завершатся во втором поле. Это должно быть достаточно легко исправить с помощью второго поиска/замены, но я был бы признателен за его исправление. –

0

Что-то вроде этого?

^Name,(\((?:W|H|P|M)\)\d+(?:,)?)*[,]*$ 

Regular expression visualization

Edit live on Debuggex

Даст вам все матчи в каждом ряду. Тогда вам просто нужно выделить каждое совпадение в правый столбец.