2

I am very new to Swift and have trying to use regular expressions, but getting the match from the string seems to be an insurmountable task.

This is my current approach.

print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression))))

This doesn't work because

Value of optional type 'Range<String.Index>?' must be unwrapped to a value of type 'Range<String.Index>'

I guess this has something to do with it possibly being null, so now i want to provide it with an alternative using the ?? operator.

print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? Range<String.Index>())))

What i want to do is to provide it with an empty range object but it seems to be impossible to create an empty object of the type required.

Any suggestions?

3 Answers 3

2

There is simply no argument-less initialiser for Range<String.Index>.

One way you can create an empty range of String.Index is to use:

data.startIndex..<data.startIndex

Remember that you shouldn't use integers here, because we are dealing with indices of a string. See this if you don't understand why.

So:

print(data.substring(with: (data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? data.startIndex..<data.startIndex)))

But substring(with:) is deprecated. You are recommended to use the subscript:

print(data[data.range(of: "[a-zA-Z]at", options: .regularExpression) ?? data.startIndex..<data.startIndex])
Sign up to request clarification or add additional context in comments.

Comments

1

Instead of trying to create an empty range, I would suggest creating an empty Substring in case there was no match. Range can be quite error-prone, so using this approach you can save yourself a lot of headaches.

let match: Substring
if let range = data.range(of: "[a-zA-Z]at", options: .regularExpression) {
    match = data[range]
} else {
    match = ""
}
print(match)

Comments

0

You can create such constructor with a simple extension to Range type. Like this:

extension Range where Bound == String.Index {
    static var empty: Range<Bound> {
        "".startIndex..<"".startIndex
    }

    init() {
        self = Range<Bound>.empty
    }
}

Then it can be used like this:

let str = "kukukukuku"
let substr1 = str[str.range(of: "abc", options: .regularExpression) ?? Range<String.Index>()]
let substr2 = str[str.range(of: "abc", options: .regularExpression) ?? Range<String.Index>.empty]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.