Target double quotes using regular expressions in Swift

Viewed 2830

I have been trying to extract a piece of text inside an string using regular expressions in Swift. The text I want to extract is inside double quotes so I'm trying to target those double quotes and get the piece of text inside.

This is the RegExp that I'm using: (?<=")(?:\\.|[^"\\])*(?=")

It work pretty well with any kind of text and it could be even simpler since I'm looking for anything that could be inside those double quotes.

When I try to use this RegExp with Swift I have to scape the double quotes in it, but for some reason the RegExp doesn't work with escaped double quotes e.g. (?<=\")(?:\\.|[^\"\\])*(?=\").

Even if I try some as simple as this \" the RegExp doesn't match any double quote in the string.

Code Example

func extractText(sentence: String?) -> String {
    let pattern = "(?<=\")(?:\\.|[^\"\\])*(?=\")"
    let source = sentence!

    if let range = source.range(of: pattern, options: .regularExpression) {
        return "Text: \(source[range])"
    }

    return ""
}

extractText("Hello \"this is\" a test") -> "this is"

To have in mind:

  • All these RegExps must be inside double quotes to create the string literal that is going to be used as a pattern.
  • I'm using the String's range method with the .regularExpression option to match the content.
  • I'm using Swift 4 with an Xcode 9 Playground

How can I scape double quotes in Swift to successfully match these in a string?

Solution

Thanks to @Atlas_Gondal and @vadian I noticed the problem "in part" is not the RegExp but the string I'm getting which is using a different type of double quotes “ ... ” so I have to change my pattern to something like this "(?<=“).*(?=”)" in order to use it.

The resulted code looks like this:

func extractText(sentence: String?) -> String {
    let pattern = "(?<=“).*(?=”)"
    let source = sentence!

    if let range = source.range(of: pattern, options: .regularExpression) {
        return "\(source[range])"
    }

    return ""
}
3 Answers

Even though it's a bit late, I've fixed it by using a raw string.

Since Swift 5 you can do this:

let pattern = #"(?<=“).*(?=”)"# // <- Note the # in front and after.
// ...

And you are good to go. By far the simplest solution in my opinion!

⚠️ Note: This means that every character inside of the double quotes gets taken literally (no more templating ("\(variable)" or new lines \n)).

Here is a great article about raw strings.

Related