Проблема в том, что вы действительно то, что грамматик, описывающий ваш вход. Попытка описать все это одним движением становится очень сложной, очень быстрой. См. 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.
Если вы не определяете все возможные особые случаи, вы столкнетесь с вещами, делающими это перерыв регулярным выражением.Я не могу определить идеальное регулярное выражение, так что у вас есть два варианта:
- Patch регулярного выражения в еще большую сложность, как частные случаи определены
- Редизайна, чтобы избежать необходимости в сложные регулярных выражениях
Если у вас выберите вариант 1, затем это регулярное выражение исправит вашу текущую проблему:
/^-MEMBER:\s+(\b[^,]+),?(?:\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/
Большое спасибо, Sputnick, который решил мою проблему! – flipout