tags:

views:

99

answers:

2

I'm not very well versed with regular expressions. I've had to use them, maybe once every few years, and that was mostly for course work. Anyways, the following question should be a fairly straight forward question/answer for anyone familiar with regular expressions.

I need to ensure that the text entered into a field follows the following format:

x y z

or

x,y,z

or

x y z / <same pattern can repeat for almost unlimited length>

or

x,y,z / <...> // Spaces after the comma are ok

where x, y and z can only be integers. The patterns cannot be intermixed, so you cannot have

x, y, z / x y z / ...

I've tried the following

([1-9] [1-9] [1-9])

to get the x y z part, but I don't know how to include the '/' nor the ','

Any suggestions?

+5  A: 

Try to break your regular expression down into pieces. Then try to combine them.

For example, an integer like 1024 is a sequence of one ore more digits, i.e. [0-9]+. Etc.

Grammar:

digit     ::= [0-9]
space     ::= [ ]
slash     ::= [/]
comma     ::= [,]

integer   ::= digit+
separator ::= space | comma
group     ::= integer separator integer separator integer
group-sep ::= space slash space
groups    ::= group ( group-sep group )*

Regex:

([0-9]+[ ,][0-9]+[ ,][0-9]+)([ ][/][ ][0-9]+[ ,][0-9]+[ ,][0-9]+)*
dtb
+1. Just FYI, this will allow the mixing of commas and spaces within a group of integers. Not sure if that's an issue, but I read the OP's requirements as being one or the other.
Adam Robinson
Matches `1,2 3` which I'm not sure if it's valid for the OP.
BrunoLM
It cannot mix between commas and spaces, so it would have to be:1 2 3 OR 1,2,3 and this is ok too 1, 2, 3
Agent Worm
@Agent: See my answer for a bit of explanation on `\\N`
BrunoLM
+3  A: 

I guess you can use

Regex r = new Regex("^([0-9]+([ ,]|, )[0-9]+(\\2)[0-9]+)( [/] ([0-9]+(\\2)[0-9]+(\\2)[0-9]+)+)*$");

var x1 = r.IsMatch("1,2 3");         // false
var x2 = r.IsMatch("1 3 2 / 1 2 3"); // true
var x3 = r.IsMatch("1,3,2");         // true
var x4 = r.IsMatch("1 3 2 / 1");     // false

Console.WriteLine((x1 == false) ? "Correct" : "Error");
Console.WriteLine((x2 == true) ? "Correct" : "Error");
Console.WriteLine((x3 == true) ? "Correct" : "Error");
Console.WriteLine((x4 == false) ? "Correct" : "Error");
Console.ReadLine();

Spliting in smaller pieces

[0-9]+  matches any number, even 0. If it can't start with 0
        you will have to change it
[ ,]    the separator allows a space or a comma
\\2     matches the same thing the second group matched (space or comma)

The second big parenthesis matches or not more iterations of this sequence if started by /.

If all separator needs to be exactly the same, replace them by \\2 (just don't replace the first, that is what it is going to match for the group 2).

BrunoLM
I tested what you suggested using this [REGex Tester](http://www.regextester.com/), it didn't seem to work for the case with commas. Perhaps I missed something.However, I tried your suggestion through DevExpress' XtraGrid TextEditor MaskEditor (a mouthful I know). But reading through documentation it says they do not support back references, which I'm assuming the `\\2` is supposed to do. So unless there's a way to strictly enforce a space or a comma (but not both) , I'll just have to settle for a mixed mode.
Agent Worm
Or simply replace a `,` with a space would work too.
Agent Worm
If it's not supported then I'm afraid to manage the mix with something else. I've tested this expression on a console project.
BrunoLM
I figured out how to incorporate your suggestion into what I needed to do. Except, `r.IsMatch("1 3 2 / 1")` returns true. I only want it to return true if and only if it's written out with the 3 coordinates for each "section" or whatever you want to call it; `1 2 3 / 1 2 3`. Etc. I'll keep playing around with it. I really appreciate your help.
Agent Worm
It was matching `1 2 3 / 1` because I missed start (`^`) and end (`$`). I've fixed the code.
BrunoLM
Seems to work like a charm. Thanks you for your help!
Agent Worm