2

I'm trying to parse the location entries from a .ics file as follows seen in the image below . Normally this works fine even though the only tester I can find is PCRE rather than ICU as I just need to add an extra backslash to any special characters.

However in swift I get the following results:

"^Location" //No Match
"^VERSION" //No Match
"^BEGIN" //Match
"^ :" //Match

Can I get the '^' anchors to function like they do in the PCRE tester?

PCRE regex tester PCRE regex tester

Code

func testParticipantParsing()
{
    //let locationRegex = "^LOCATION:(.*(?:\\n :?.*)*)"
    let locationRegex = "LOCATION:(.*(?:\\n :?.*)*)"
    var regex : NSRegularExpression! = nil
    var resultsArray = [String]()

//Parse for location
    do
    {
        regex = try NSRegularExpression(pattern: locationRegex, options: NSRegularExpressionOptions.init(rawValue: 0))
        let nsString = content as NSString
        let results = regex.matchesInString(content, options: [], range: NSMakeRange(0, nsString.length))
        resultsArray = results.map{ nsString.substringWithRange($0.range) }
    }
    //Catch errors if regex fails
    catch
    {
        print("invalid regex")
    }
    //Strip .ics new line tokens
    for var result in resultsArray
    {
        result = result.stringByReplacingOccurrencesOfString("\n :", withString: "")
        result = result.stringByReplacingOccurrencesOfString("\n ", withString: "")
        print(result)
    }
}
Declan McKenna
  • 4,321
  • 6
  • 54
  • 72
  • 1
    Note that your regex does not deal with different case of `LOCATION`, parameters in that property, and the keyword `LOCATION` being split over multiple lines, all of which are valid things to do in iCalendar. You're better off using a real parser. – Evert Jan 22 '16 at 16:05
  • @Evert I'd like to but with swift 2 being relatively new I can't find anything; or at least not with the correct license. I may have misunderstood you but I think I've dealt with this with the line anchor as all instances were the user creates a new line themselves appear to have the separator ' :' appended to the beginning of the new line or ' ' if the line has occurred naturally as seen on the 11th line. I may have missed something do you think there are times when '\nLOCATION:' could appear together? – Declan McKenna Jan 23 '16 at 00:24
  • just to give you an example, this is also valid: `lOcA\r\n\ttION;x-param=foo;x-param2="hello::":actualvalue\r\n` – Evert Jan 23 '16 at 01:11

1 Answers1

2

Just add the (?m) at the start of your pattern.

let locationRegex = "(?m)^LOCATION:(.*(?:\\n :?.*)*)"
                     ^^^^

The (?m) is the inline modifier version of the MULTILINE modifier that forces ^ to match the location at the beginning of a line rather than string (and makes $ match the location at the end of the line, before the newline sequence).

See Table 4: Flag Options:

m flag:
Control the behavior of ^ and $ in a pattern. By default these will only match at the start and end, respectively, of the input text. If this flag is set, ^ and $ will also match at the start and end of each line within the input text.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    Perfect, I didn't know about these flags. Thanks. – Declan McKenna Jan 22 '16 at 11:28
  • Oh, there can be funnier situations with these inline modifiers, see [What is '?-mix' in a Ruby Regular Expression](http://stackoverflow.com/questions/28630936/what-is-mix-in-a-ruby-regular-expression). It was not any "mix" :) – Wiktor Stribiżew Jan 22 '16 at 11:29