Skip to main content
GameDev.net gamedev.net
🔒 Locked

C# .NET2.0 Regex troubles.

Started by Manaxter Nov 1, 2006 at 5:13 AM 1 replies 1.3k views
Original Post
Manaxter
Manaxter
Hi Guys. I'm making a program that needs to take a text file as input and split it up into strings. However, it is a complicated (and unchangeable) format. The format is as such.

One line of text here.
.i Perhaps some text here, but it is optional.

.1
Here is some more text, possibly with punctuation.
And it goes on like this for several lines.

.
Then we have a little non-numbered one here.

.2
And then here!

What I need to do is extract a string from the '.1' to the next '.', including the '.1', not including the next '.'. At any time there may be a number after the dot, there may not be. I then need from the '.' to the '.2' etc etc. I've started a previous incarnation of this thing in VB.NET, using the regex string "\.\d\s.*?(?=\.\d)|\.\d.*?$" however that does not allow for the little fellow in the middle there. The closest I could come up with for my situation was "\r\n\r\n\.\d[a-zA-Z0-9*]" however that will not work at all, because that will stop when it reaches some punctuation, and I need it to pass over unless that punctuation is a period on a line by itself OR has a number after it. It's very complicated and I had the last regex expression made for me, so I have no idea. Any help would be much appreciated. Cheers Jacob.
"You're worth all the discount milk in the world!" - Mum
kryat
kryat
For some reason I love making regexes.

            String in_str = @"One line of text here..i Perhaps some text here, but it is optional..1Here is some more text, possibly with punctuation.And it goes on like this for several lines..Then we have a little non-numbered one here..2And then here!";            MatchCollection matches = Regex.Matches(in_str, @"(?:\r?\n)(\.\w?)(?:\s*)(.+?)(?=\r?\n?\r?\n\.\w?|$)", RegexOptions.Singleline);            foreach (Match m in matches)            {                Console.WriteLine("[{0} = {1}]", m.Groups[1].Value, m.Groups[2].Value);            }            Console.WriteLine(matches.Count);


You need to use regex lookarounds, in this case a zero width positive lookahead (?=...). Whenever a set of characters is matched by a regex is it effectively "consumed", and those characters wont match any subsequent matches in the string. By using a lookaheads you can look forward in the string and match a sequence without actually removing it from whats left to do (in this case a \r\n\r\n\.\w? ).

I dont know if that made any sense, but thats what you needed to do. The regex above works on the sample text, the only place i could see it failing is the following:

.10 Here is a long line of text and this probably will break the current regex. That period right there could screw this thing up, but a hanging period likethat should really go with the line above it


you could catch that by changing the look ahead to (?=\r?\n\r?\n\.\w?|$) and requiring it to look for a blank line before the next . header. I'm not sure if the source text actually follows that convention, but if it does that should give you the most acurate matching.

Also, i'd just shift the first line "One line of text here." out on its own, rather than trying to make one regex do it.
Manaxter
Manaxter
Well hopefully the people writing these text files wont be so stupid to do the last situation you showed! Thanks man, that was really helpful. I think I need to actually learn how it works now!

Cheers
Jacob
"You're worth all the discount milk in the world!" - Mum

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.