2013-03-14 2 views
1

У меня возникли проблемы соответствия регулярных выражений в Perl и было интересно, если кто-то какие-либо понять:Проблемы с Regex соответствия в Perl

Вот мое регулярное выражение: /^-MEMBER:\s+(\b[^,]+)(?:,\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/

Вот что я сопрягая:

-Член: Doe, John H ID #: 3907

регулярное выражение прекрасно работает и соответствует выше линии, но у меня возникают полукомбинезоны bles с любыми строками, которые не могут содержать имя и среднее. Пример ниже:

-Член: Doe, ID #: 3907

У меня возникли проблемы соответствия с текущим регулярным выражением, обе линии.

Спасибо за помощь!

ответ

0

Это регулярное выражение будет соответствовать обе строке:

/ 
    ^-MEMBER:\s+   # the beginning of the line with "-MEMBER: " 
    .*?     # non greedy 
    \s+ID#:\s+(\d+)$  # space and end ID part 
/x 
+0

Большое спасибо, Sputnick, который решил мою проблему! – flipout

1

Вы разместили свой матч разделителей внутри необязательного ПгвЬЫате группы, так что вы можете соответствовать только запятой в присутствии FirstName. Если запятые будут сопровождать фамилии без первых имен, вам необходимо переместить их в группу фамилий.

/^-MEMBER:\s+(\b[^,]+,)(?:\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/ 
0

Проблема в том, что вы действительно то, что грамматик, описывающий ваш вход. Попытка описать все это одним движением становится очень сложной, очень быстрой. См. Perl yapp module для альтернативы.

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

/^-MEMBER: # start of line, match specific string 
\s+ # must be followed by at least one whitespace char 
(\b[^,]+) # now we need to match a word in a capture group 
(?:,\s(\b.{1,50}\b)\.?)? # here's the pain, so lets deal with it below 
\s+ # more whitespace 
ID#: # match this string 
\s+ # and some more whitespace 
(\d+)$/ # digits at the end of the line 

(
?: # cluster the following 
,\s # comma, then a single space 
(
    \b.{1,50}\b # up to fifty "things" bounded by words 
) # another capture group 
\.? # optional period 
)? # zero or one of these I.E. optional capture 

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

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

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

Обратите внимание, как ваше регулярное выражение пытается определить, что является «действительным» в каждом разделе. Фамилия (\b[^,]+) может иметь что-нибудь помимо запятой! Это то, что вы хотите? Что произойдет, если действительные имена могут содержать только [a-zA-Z_]? Является ;injectionattemptFTW!!;# действительным именем? Создайте свою программу, чтобы был ограниченный и очевидный набор условий. If a then valid, else fail легко рассуждать о простых a s.

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

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

Если у вас выберите вариант 1, затем это регулярное выражение исправит вашу текущую проблему:

/^-MEMBER:\s+(\b[^,]+),?(?:\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/ 
Смежные вопросы