Можно ли сделать что-то подобное с регулярным выражением? если нет, каковы альтернативы? - PullRequest
0 голосов
/ 17 января 2012

Предположим, у меня есть текстовый файл с некоторыми данными, которые я хочу восстановить, потерянными в море обычного письменного языка.
Каждый фрагмент данных, который я хочу получить, представляет собой набор из 3 чисел от 0 до 99 (который я будувызовите номера от N1 до N3), которые можно отформатировать 4 разными способами:

  • N1-N2-N3
  • N1N2N3
  • N1.N2.N3
  • N1/N2/N3

Можно ли с помощью регулярных выражений описать что-то подобное:
Что-то, что я назову separator, позже будет что-то в этом списке: [ '-', '', '.', '/' ]
Мое выражение лица такое: N1{separator}N2{same_separator_as_the_first_one}N3?

Кажется, что единственный способ выразить это:
Мое выражение выглядит так: ({N1}-{N2}-{N3}) OR ({N1}{N2}{N3}) OR ({N1}.{N2}.{N3}) OR ({N1}/{N2}/{N3})

... который быстро становится нечитаемым ...

Можно ли получить выражение первого типа с помощью регулярных выражений?Есть ли что-то доступное, не являющееся регулярным выражением, которое допускает такую ​​выразительность?

Реальный вопрос:

Учитывая доступные форматы, каков наилучший способ написать функцию, котораяполучает строку и возвращает от N1 до N3 вместе с используемым символом-разделителем (и выдает исключение, если строка не соответствует ни одному формату)?

Ответы [ 4 ]

4 голосов
/ 17 января 2012

Это немного зависит от вида регулярного выражения, но на типичном языке я бы написал:

([1-9]?[0-9])([-./]?)([1-9]?[0-9])\2([1-9]?[0-9])

Тогда группа 2 - это разделитель, а группы 1, 3 и 4 - это три числа..

1 голос
/ 17 января 2012

Ваше регулярное выражение должно выглядеть следующим образом:

N1([-\./])N2\1N3

Где \1 указывает «все, что было найдено внутри первой круглой скобки», например, все, что соответствовало [-\./].Конечно, в случае без разделителя вам нужно знать больше о форме N1 и N2, чтобы гарантировать совпадение.Если «целое число» - это все, что у вас есть, у вас могут возникнуть трудности (когда заканчивается N1 и начинается N2?).

То, что вы ищете, в общем, так называемыеРекомендации'.Смотрите здесь: http://www.regular -expressions.info / brackets.html .

0 голосов
/ 17 января 2012

Вот как это сделать, используя Регулярное выражение Python библиотека:

>>> import re
>>>
>>> text = '''12-34-56
... 654321
... 24.68.10
... 1/86/42
... Nonsense
... 00-000-0000-00000
... '''
>>>
>>> for line in text.split('\n'):
...     m = re.match(r'^(\d{1,2})([-/.]?)(\d{1,2})\2(\d{1,2})$', line)
...     if m:
...         print m.group(1), m.group(3), m.group(4), 'were separated by [', m.group(2), ']'
...     else:
...         print '[', line, ']', 'was badly-formed'
...
12 34 56 were separated by [ - ]
65 43 21 were separated by [  ]
24 68 10 were separated by [ . ]
1 86 42 were separated by [ / ]
[ Nonsense ] was badly-formed
[ 00-000-0000-00000 ] was badly-formed
[  ] was badly-formed
0 голосов
/ 17 января 2012

В формальном определении регулярного выражения вы не можете иметь «тот же разделитель, что и последний», не перечисляя их, как вы делали это в своем «быстро нечитаемом» решении. Вам нужна контекстно-свободная грамматика, чтобы «запомнить» что-то подобное; К счастью (как уже отмечали другие), большинство реализаций регулярных выражений включают такие возможности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...