2015-07-06 2 views
5

Рассмотрим M, T, W, TH, F, S, SU - дни недели.Матч ровно в одном случае с регулярным выражением

У меня есть регулярное выражение, которое работает хорошо для одного сценария, за исключением, когда нет последовательности дней недели, т.е. нет M, T, W, TH, F, S, SU в ожидаемом месте внутри строки.

Например, q10MT действителен, но q10HT недействителен.

Ниже мое выражение:

string expression = "q(\\d*)(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)?"; 

В случае q10MT, выход q10MT, который является правильным, но в случае q10HT выход q10 что неправильно, мой регулярное выражение не должно возвращать никакого значения или пустые если совпадение отсутствует.

Какие изменения необходимо внести для достижения этой цели?

+2

К сожалению, совершенно бесполезный комментарий, но я должен сказать, что я любил '(W)? (TH)? (F) 'part :-) – Konamiman

+0

Это требование, чтобы дни были в порядке? IE должен включать «T» в захваченную «q10MWT»? – Taemyr

+0

Как насчет выражения типа 'q10MTHSSUT', которое пропускает дни и распространяется на следующую неделю. Это законно? Что вы ожидаете отсюда? – holroy

ответ

5

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

q(\\d*)(?=(?:M|T(?!H)|W|TH|F|S(?!U)|SU))(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)? 

Или, как было отмечено @Taemyr, более короткий эквивалент

q(\\d*)(?=(?:M|TH?|W|TH|F|SU?))(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)? 

Вот demo

(?=(?:M|TH?|W|F|SU?)) взгляд -ahead гарантирует, что есть как минимум одно требуемое значение из списка альтернатив, который у вас есть после ожидания.

C использование # регулярное выражение:

var rx = new Regex(@"q(\d*)(?=(?:M|TH?|W|TH|F|SU?))(M)?(T(?!H))?(W)?(TH)?(F)?(S(?!U))?(SU)?"); 
var result = rx.Match("q10MSUT").Value; 

Результат:

enter image description here

+0

Да, это работает очень хорошо. Спасибо :-) Можете ли вы дать мне простой/простой пример использования (? = (?: – Gaurav123

+0

) Я немного озадачен: вы, должно быть, некоторое время используете свое регулярное выражение, не так ли? дни, как если бы мы совпадали с 'M', возвращаем' Monday'? –

+1

'(T (?! H) | TH)' То же, что и '(TH?)', аналогично для '(S (?! U) | SU) ' – Taemyr

1

Что можно сказать о следующем:

q(\d*)(M|TH?|W|F|SU?)+ 

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

Помните, что это решение не требует, чтобы дни были в порядке и позволяли пропускать дни, указанные в комментариях, не иметь значения.

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

1

Если заказ не имеет значения, вам нужно сделать что-то подобное;

q(?<number>\d+)((?<monday>(?<!M\D*)M)|(?<tuesday>(?<!T(?!H)\D*)T(?!H))|(?<wednesday>(?<!W\D*)W)|(?<thursday>(?<!TH\D*)TH)|(?<friday>(?<!F\D*)F)|(?<saturday>(?<!S(?!U)\D*)S(?!U))|(?<sunday>(?<!SU\D*)SU))+ 

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

Каждый будний день фиксируется в собственной группе захвата, и эта группа называется так, что ее можно извлечь позже. «q10MTsomething» будет захватывать «q10MT» с 10 в группе захвата «число», M в группе захвата «понедельника» и T в группе захвата «по вторникам», другие группы захвата будут пустыми. «q10TFMother» будет захватывать «q10TFM» с захватом, как в предыдущем примере, плюс F в группе захвата «пятница». «q10TFMT» будет захватывать «q10TFM» с помощью групп захвата, как в предыдущем примере. «q10HT» не будет соответствовать.

demo

Обратите внимание, что это строка регулярного выражения. Если ввести код, вам может понадобиться избежать \ s для создания правильной строки.

+0

Выход '' q10WMTTH'' должен быть '' q10W'', но его отображение '' q10WMTTH'' неверно. – Gaurav123

1

Вопрос уже ответ. Даже я хочу указать на другую идею, используя переменную длину lookbehind для поддержания последовательности, которая должна быть fine with .NET

q(\d*)[MTWFSUH]+(?<=q\d*(M)?(T)?(W)?(TH)?(F)?(S)?(SU)?) 
  • [MTWFSUH] список допустимых символов. По крайней мере, один требуется
  • Использование просмотра назад для согласования тех пор, пока последовательность сохраняется

Test at your test tool

+1

@ Gaurav123 Если вам не требуется полное совпадение (только захваты), можно даже сократить его до '[MTWFSUH] + (? <= Q (\ d *) (M)? (T)? (W)? (TH)? (F)? (S)? (SU)?) '. –

+1

Мне очень понравилось, как вы это объяснили. – Gaurav123