2014-01-27 4 views
0

У меня есть регулярное выражение, которое отлично работает в настоящее время. Но теперь я хочу добавить к нему, чтобы фиксировать даты.Regex not capture date

Текущее регулярное выражение:

(?<GeneralHelp>^/help\s*)? 
(?:/client:) 
(?<Client>\w*) 
(?:(?:\s*/(?<ClientHelp>help))*)* 
(?:(?:\s*/)(?<Modules>createHistory)(?:(?:\s*/(?<ModuleHelp>help))*)*)* 

Я добавил в конце:

(?:(?:\s*/)(?<StartDate>^([0]?[1-9]|[1|2][0-9]|[3][0|1])[. -]([0]?[1-9]|[1][0-2])[. -]([0-9]{4}|[0-9]{2})$))*)* 
(?:(?:\s*/)(?<EndDate>^([0]?[1-9]|[1|2][0-9]|[3][0|1])[. -]([0]?[1-9]|[1][0-2])[. -]([0-9]{4}|[0-9]{2})$))*)* 

Используя приведенный ниже пример, он просто не получит даты, но это не соответствует всем остальным.

/client:testClient/createHistory/11-11-2013/11.11.2013 

Это регулярное выражение используется, чтобы разбить Main одна строка в параметре массива строк из консольного приложения. Никто из моей команды не «свободно» в регулярном выражении, и у нас нет времени свободно говорить. Мы работаем с тем, что можем, и это дополнение - это то, о чем я думал сегодня, который может иметь с большими проблемами то, что у нас есть с нашим проектом, и мы быстро работаем. Поэтому любая помощь будет оценена по достоинству.

+0

Вы должны добавить некоторые примеры данных, к которым применяется регулярное выражение. Также преднамеренно, что вы не избежали '.' и' -' внутри '[. -] '? Насколько я знаю, они все равно должны интерпретироваться, поэтому '.' Будет соответствовать любому символу, а не только периодам. – Mario

+0

@Mario: na, [. -] означает «матч., пробел или -». поскольку «-» является последним в классе символов, нет проблем с сопоставлением непреднамеренных диапазонов. –

+0

@Mario: внутри квадратных скобок, '.' - это просто точка и' -' просто дефис, если он находится рядом с скобкой. @Kendra: есть ли причина, по которой вы используете неселективные скобки на '(?: \ S * /)'? – Robin

ответ

1

Во-первых, ^ в вашем регулярном выражении означает «начало строки», то есть вы хотите только совместить дату в начале строки (что неверно для вас). Так что удалите его. То же самое с «$», что означает «конец строки».

Во-вторых, [0|1] означает «совпадающие символы 0, 1 или 1». Вероятно, вы хотите, чтобы [01] означало «совпадающие символы 0 или 1».

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

В-четвертых, как общая точка стиля, [0] - это то же самое, что и 0, поэтому квадратные скобки здесь избыточны.

Так что ваши (! Не совсем) «фиксированный» регулярное выражение:

(?:(?:\s*/)(?<StartDate>(0?[1-9]|[12][0-9]|[3][01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))* 
(?:(?:\s*/)(?<EndDate>(0?[1-9]|[12][0-9]|3[01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))* 

Однако это не соответствовать вашей тестовой строки из-за дополнительного «/ testModule» в строке, которая не находится в ваше рабочее регулярное выражение где угодно. Вы можете изменить исходное регулярное выражение, чтобы разрешить дополнительные косые черты между двумя частями регулярного выражения?

<original regex> 
(?:/[^/]+)* # <-- for the /testModule and any other similar tokens that appear in between 
<date regex> 

Также в качестве общей точки

  • у вас есть несколько вхождений (?:(?:regex)*)*. Я не уверен, что суть удвоения внешнего *, кроме того, что синтаксический анализатор регулярных выражений работает намного труднее, чем нужно, без всякой причины (внешний (?:)* здесь избыточен).
  • нет смысла делать (?:/\s*), как вы ничего с кронштейнами не делать, так что просто сделать /\s*
  • же с такими вещами как (?:/client:). Почему бы не захватывать скобки, если вы ничего не делаете с ними. /client: сделаю.
  • (?:regex)* означает «соответствует 0 на бесконечность вхождениях regex». С такими вещами, как (?:\s*/(?<ClientHelp>help))*, вы действительно ожидаете, что это произойдет бесконечно много раз в вашей строке, или оно появится только один раз или совсем?Рассмотрим замену * на ?, что означает «совпадение 0 или 1 вхождения» (если вы знаете, что этот токен появится один или несколько раз) или замените его (скажем) {0, 100}, если вы знаете, что этот токен появится на 100 раз (и не менее 0 раз). Это может повысить производительность.

Так что рекомендую изменить регулярное выражение, как это:

(?<GeneralHelp>^/help\s*)? 
/client: 
(?<Client>\w*) 
(?:\s*/(?<ClientHelp>help))* 
(?:\s*/(?<Modules>createHistory)(?:\s*/(?<ModuleHelp>help))*)* 
(?:/[^/]+)* 
(?:\s*/(?<StartDate>(0?[1-9]|[12][0-9]|[3][01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))* 
(?:\s*/(?<EndDate>(0?[1-9]|[12][0-9]|3[01])[. -](0?[1-9]|1[0-2])[. -]([0-9]{4}|[0-9]{2})))* 

Вы можете возиться с регулярным выражением в regexr, где я создал пример с регулярным выражением/тестовой строкой. (Изменить: < и> в регулярном выражении, кажется, были изменены на < и > в RegExr поэтому ссылка не будет работать, если не копировать/вставить регулярное выражение я написал прямо)

+0

Хороший довольно обширный ответ! – Robin

+0

Спасибо, но он все еще не захватывает даты. –

+0

Пожалуйста, определите, что «не работает». Если вы скопируете/вставьте это регулярное выражение в regexr с помощью тестовой строки, группы будут отображены как ожидалось. Возможно, вы делаете что-то неправильно в своей реальной реализации регулярного выражения (вызывая неправильную функцию или не избегая некоторых специальных символов и т. Д.). Возможно, обновление исходного вопроса с помощью дополнительной информации. –

0

Если вы уверены, эти два последних поля даты, вы можете просто добавить что-то вроде

(?<StartDate>(?:\d+[. -]?){3})/(?<EndDate>.*)$ 

(или даже (?<StartDate>[^/]+)/(?<EndDate>.+)$, если ваши дела все по той же схеме, и это соответствует вашим потребностям).

Также, как уже указано математическим.coffee, первое регулярное выражение может быть улучшено.