Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex option "Multiline"

Tags:

c#

regex

I have a regex to match date format with comma.

yyyy/mm/dd or yyyy/mm

For example:

2016/09/02,2016/08,2016/09/30

My code:

string data="21535300/11/11\n";
Regex reg = new Regex(@"^(20\d{2}/(0[1-9]|1[012])(/(0[1-9]|[12]\d|30|31))?,?)*$", 
                      RegexOptions.Multiline);

if (!reg.IsMatch(data))
    "Error".Dump();
else
    "True".Dump();

I use option multiline. If string data have "\n". Any character will match this regex.

For example:

string data="test\n"
string data="2100/1/1"

I find option definition in MSDN. It says:

It changes the interpretation of the ^ and $ language elements so that they match the beginning and end of a line, instead of the beginning and end of the input string.

I didn't understand why this problem has happened. Anyone can explan it? Thanks.

like image 597
Yich Lin Avatar asked Oct 29 '22 21:10

Yich Lin


1 Answers

Your regex can match an empty line that you get once you add a newline at the end of the string. "test\n" contains 2 lines, and the second one gets matched.

See your regex pattern in a free-spacing mode:

^                 # Matches the start of a line
 (                # Start of Group 1
   20\d{2}/
   (0[1-9]|1[012])
   (/
     (0[1-9]|[12]\d|30|31)
   )?,?
 )*                # End of group 1 - * quantifier makes it match 0+ times
$                  # End of line

If you do not want it to match an empty line, replace the last )* with )+.

An alternative is to use a more unrolled pattern like

^20\d{2}/(0[1-9]|1[012])(/(0[1-9]|[12]\d|3[01]))?(,20\d{2}/(0[1-9]|1[012])(/(0[1-9]|[12]\d|3[01]))?)*$

See the regex demo. Inside the code, it is advisable to use a block and build the pattern dynamically:

string date = @"20\d{2}/(0[1-9]|1[012])(/(0[1-9]|[12]\d|3[01]))?";
Regex reg = new Regex(string.Format("^{0}(,{0})*$", date), RegexOptions.Multiline);

As you can see, the first block (after the start of the line ^ anchor) is obligatory here, and thus an empty line will never get matched.

like image 141
Wiktor Stribiżew Avatar answered Nov 15 '22 04:11

Wiktor Stribiżew