Question

I'm trying to work with the content of a .ics file in C#. In my first step all i want to do is splitting the whole content of the file by events. I'm trying to achieve this with a regex, which i never used before. One event always starts with "BEGIN:VEVENT" and ends with "END:VEVENT".


My code:

    MatchCollection iCalMatches = Regex.Matches(iCal, @"BEGIN:VEVENT(.*)END:VEVENT");

    string testString = "";
    foreach (Match match in iCalMatches) {
        testString += match.Value + "<br/><br/>";
    }
    return testString;

"iCal" contains the whole ics content without any line breaks.


Input/Output:

So the files content looks something like this:

BEGIN:VEVENT

...

END:VEVENT

BEGIN:VEVENT

...

END:VEVENT

But instead of two results containing ....

BEGIN:VEVENT

...

END:VEVENT

... i get one result containing the whole content.


PS: I know there are libraries for this but still want to make it work this way.

Was it helpful?

Solution

You need to use lazy repetition. By default, Regex tries to get as much as possible (greedy) if you use repetition through stars, curly braces, pluses and others. If you want to activate lazy repetion, replace (.*) with (.*?).

OTHER TIPS

You can use a lazy match instead:

@"BEGIN:VEVENT(.*?)END:VEVENT"
                 ^

By inserting the ?, it makes the .* match as little as possible (as opposed to as much as possible) until the next END:VEVENT.

As the other answers indicate, using a lazy match you will be able to get what you need.

Alternatively, you can write some simple code that parses the whole calendar into a list of string-string dictionaries.

string[] lines = File.ReadAllLines("data.ics");
var events = new List<Dictionary<string, string>>();
int eventIndex = -1;
foreach (var line in lines)
{
    if (line == "BEGIN:VEVENT")
    {
        events.Add(new Dictionary<string,string>());
        eventIndex++;
    }
    else if (line != "END:VEVENT")
    {
        int positionOfColon = line.IndexOf(':');
        if (positionOfColon == -1) continue;
        string propertyName = line.Substring(0, positionOfColon - 1);
        string propertyValue = line.Substring(positionOfColon + 1);
        events[eventIndex].Add(propertyName, propertyValue);
    }
}

Each dictionary represents a single event, each entry a line from the ics file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top