Нужна помощь в построении регулярного выражения - PullRequest
2 голосов
/ 20 июля 2011

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

"Sun,Mon,Tue,Wed,Thu,Fri,Sat"

Каждый день может появляться в строке не более одного раза. Порядок дней важен.

До сих пор я пробовал следующие шаблоны:

1) (Sun,|Mon,|Tue,|Wed,|Thu,|Fri,|Sat,)*(Sun|Mon|Tue|Wed|Thu|Fri|Sat)

Это очень плохо: допускает многократное присутствие дней, а также не следит за порядком дней.

2) (Sun)?([,^]Mon)?([,^]Tue)?([,^]Wed)?([,^]Thu)?([,^]Fri)?([,^]Sat)?

Это лучшее, что я получил до сих пор. Единственная проблема здесь состоит в том, что она соответствует строкам, начинающимся с запятой, например, ,Mon,Tue,Fri. Мой вопрос заключается в том, как отфильтровать начальную строку запятой, соответствующую этому шаблону.

Заранее спасибо.

Ответы [ 4 ]

5 голосов
/ 20 июля 2011

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

(?!,)(Sun)?([,^]Mon)?([,^]Tue)?([,^]Wed)?([,^]Thu)?([,^]Fri)?([,^]Sat)?

Однако я неЯ не думаю, что [,^] делает то, что, как вы думаете, делает - в привычных для меня регулярных выражениях ^ в квадратных скобках соответствует литералу ^, когда это не первый символ в списке - он не соответствуетначало строки.Вы можете заменить его на (^|,):

(?!,)(Sun)?((^|,)Mon)?((^|,)Tue)?((^|,)Wed)?((^|,)Thu)?((^|,)Fri)?((^|,)Sat)?
4 голосов
/ 20 июля 2011

Это немного сложно, но отвечает всем вашим требованиям. Может быть, регулярное выражение не лучшее решение для этого ...

^(Sun(,(?=.)|$))?(Mon(,(?=.)|$))?(Tue(,(?=.)|$))?(Wed(,(?=.)|$))?(Thu(,(?=.)|$))?(Fri(,(?=.)|$))?(Sat)?$

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

^         # start of string
(         # Try to match...
 Sun      # Sun
 (        # followed by either
  ,       # a comma
  (?=.)   # but only if more text follows
 |        # or
  $       # end of string
 )
)?        # make it optional.
(Mon(,(?=.)|$))?    # same for Mon-Fri
(Tue(,(?=.)|$))?
(Wed(,(?=.)|$))?
(Thu(,(?=.)|$))?
(Fri(,(?=.)|$))?
(Sat)?    # never a comma after Sat
$         # end of string
3 голосов
/ 20 июля 2011

Другой вариант - творческое использование границ слов :

^\b(?:Sun)?,?\b(?:Mon)?,?\b(?:Tue)?,?\b(?:Wed)?,?\b(?:Thu)?,?\b(?:Fri)?,?\b(?:Sat)?$

Или, если вы не заботитесь о захвате каждый день, вы можете упростить это немного дальше:

^\b(Sun)?,?\b(Mon)?,?\b(Tue)?,?\b(Wed)?,?\b(Thu)?,?\b(Fri)?,?\b(Sat)?$

\b совпадает только между символом слова и несловесным символом. В этом случае между днем ​​и запятой или краем строки (начало или конец).
Границы слова гарантируют, что каждая запятая окружена буквами: она никогда не будет совпадать с запятой у края строки. Точно так же он никогда не будет совпадать между двумя днями, если запятая отсутствует, как в SunMon.

Пример: http://rubular.com/r/mTCU0ZWtMm

1 голос
/ 17 декабря 2014

(Я бы добавил это в качестве комментария к ответу OpenSauce, потому что он во многом обязан этому решению, но у меня недостаточно репутации, чтобы комментировать или, к сожалению, отозвать этот ответ. Пожалуйста, поддержите нас обоих, если вы найдете этот ответ полезным!)

В качестве дополнения к исходному вопросу, если вы хотите проверить, является ли строка:

  • разделенный запятыми список нулей (пустая строка) или нескольких элементов, взятых изявный небольшой набор элементов
  • элементы могут появляться в любом порядке
  • элементы могут появляться только один раз
  • без начальных или конечных запятых
  • элементы могут быть окруженыпробел

тогда у меня сработало следующее:

^(?!,)((^|,)\s*Mon\s*(?!.*Mon)|(^|,)\s*Tue\s*(?!.*Tue)|(^|,)\s*Wed\s*(?!.*Wed)|(^|,)\s*Thu\s*(?!.*Thu)|(^|,)\s*Fri\s*(?!.*Fri)|(^|,)\s*Sat\s*(?!.*Sat)|(^|,)\s*Sun\s*(?!.*Sun))*$

Например, это соответствует:

  • ""
  • "Вт, чт "
  • " чт, вт "
  • not " вт, вт "

Трюк здесь меняется на (Mon | Tue | Wed)* введите шаблон для поиска нескольких вхождений в любом порядке, но затем добавьте отрицательный прогноз длякаждый элемент, например, для Mon добавление (?!.*Mon) после того, как оно означает «если вы соответствуете Mon, убедитесь, что за ним не следует ни один из символов (.*), затем еще один Mon», а затем некоторое вдохновение отОтвет OpenSauce о том, как обеспечить наличие достаточного количества запятых.Конечно, разбрызгивание \s* обрабатывает пробелы.

...