joelparkerhenderson
joelparkerhenderson

Reputation: 35443

Swift regex: does a string match a pattern?

In Swift, what is a simple way to see if a string matches a pattern?

Pseudocode examples:

if string matches pattern ...

if string =~ pattern ...

(I have read the Swift docs and haven't seen a regex capability. I've read about adding a new =~ operator which is a good idea yet more complex than I'd like because this is for a teaching project. I have tried rangeOfString but get the error: 'String' does not have a member 'rangeOfString'. I am looking for a Swift solution, i.e. not typing NSRegularExpression. I do not need to do anything with the match result data.)

Upvotes: 52

Views: 64139

Answers (4)

Peter
Peter

Reputation: 9

In Swift 4.2 the following doesn't return nil even if the string does not match the pattern:

string.range(of: regex, options: .regularExpression, range: nil, locale: nil)

As Xcode suggests:

Comparing non-optional value of type 'NSRange' (aka '_NSRange') to nil always returns true

Therefore what I ended up using is:

if string.range(of: regex, options: .regularExpression)
        .location != NSNotFound {
    // do stuff if string matches regexp
}

Upvotes: -1

joelparkerhenderson
joelparkerhenderson

Reputation: 35443

Swift version 3 solution:

if string.range(of: regex, options: .regularExpression, range: nil, locale: nil) != nil ...

Swift version 2 solution:

if string.rangeOfString(pattern, options: .RegularExpressionSearch) != nil ...

Example -- does this string contain two letter "o" characters?

"hello world".rangeOfString("o.*o", options: .RegularExpressionSearch) != nil

Note: If you get the error message 'String' does not have a member 'rangeOfString', then add this before: import Foundation. This is because Foundation provides the NSString methods that are automatically bridged to the Swift String class.

import Foundation

Thanks to Onno Eberhard for the Swift 3 update.

Upvotes: 83

Onno Eberhard
Onno Eberhard

Reputation: 1541

The solutions mentioned above didn't work for me anymore, so I'm posting my solution here (I used an extension for String):

extension String {
    func matches(_ regex: String) -> Bool {
        return self.range(of: regex, options: .regularExpression, range: nil, locale: nil) != nil
    }
}

Example:

if str.matches("^[a-zA-Z0-9._-]{1,30}$") {
    //...
}

Upvotes: 62

David Berry
David Berry

Reputation: 41226

To get the syntax you actually ask about, you can easily define a new operator which wraps the bridged NSString functionality:

infix operator =~ {}
func =~(string:String, regex:String) -> Bool {
    return string.rangeOfString(regex, options: .RegularExpressionSearch) != nil
}

"abcd" =~ "ab*cd"
"abcd" =~ "abcde+"

Upvotes: 15

Related Questions