Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match exactly one occurrence with regex

Tags:

c#

regex

Consider M,T,W,TH,F,S,SU are days of week.

I have regex which is working well except for one scenario when there is no sequence of weekdays, i.e. there is no M, T , W , TH , F , S , SU at the expected location inside the string.

For example, q10MT is valid but q10HT is invalid.

Below is my expression:

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

In case of q10MT, the output is q10MT which is correct, but in case of q10HT the output is q10 which is incorrect, my regex should return no value or empty string when there is no match.

What changes do I need to make in order to achieve this?

like image 491
Gaurav123 Avatar asked Jul 06 '15 10:07

Gaurav123


2 Answers

You can achieve it with a positive look-ahead:

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

Or, as @Taemyr noted, a shorter equivalent

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

Here is a demo

The (?=(?:M|TH?|W|F|SU?)) look-ahead makes sure there is at least one required value from the alternation list you have after the look-ahead.

C# regex usage:

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;

Result:

enter image description here

like image 95
Wiktor Stribiżew Avatar answered Nov 14 '22 11:11

Wiktor Stribiżew


What about the following:

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

See demo with some examples on matches and no-matches. The key change in this regexp is that this one uses the + to require at least one match.

Be aware that this solution doesn't demand the days to be in order, and allows skipping of days specified in comments not to matter.

Edit: OP says in comments that he requires only one match for each day, which this solution doesn't account for.

like image 38
holroy Avatar answered Nov 14 '22 11:11

holroy