12

How to check whether a WHOLE string can be matches to regex? In Java is method String.matches(regex)

5
  • Do you only need a boolean as a result? Commented Apr 28, 2017 at 9:10
  • Yes, I only need a Bool result Commented Apr 28, 2017 at 9:19
  • Well, I doubt there is a specific method for it, can't you use ^ and $ anchors with your pattern? I mean, do you define the pattern or is it user-defined? Commented Apr 28, 2017 at 9:24
  • I have defined a pattern and I check whether text introduced by user in TextField matches to a pattern Commented Apr 28, 2017 at 9:34
  • Ok, you need to just use ^ and $ to define the start and end positions. There is .anchored option, but it works as /A in PHP, only anchors at the start of the string. Commented Apr 28, 2017 at 9:40

3 Answers 3

11

You need to use anchors, ^ (start of string anchor) and $ (end of string anchor), with range(of:options:range:locale:), passing the .regularExpression option:

import Foundation

let phoneNumber = "123-456-789"
let result = phoneNumber.range(of: "^\\d{3}-\\d{3}-\\d{3}$", options: .regularExpression) != nil
print(result)

Or, you may pass an array of options, [.regularExpression, .anchored], where .anchored will anchor the pattern at the start of the string only, and you will be able to omit ^, but still, $ will be required to anchor at the string end:

let result = phoneNumber.range(of: "\\d{3}-\\d{3}-\\d{3}$", options: [.regularExpression, .anchored]) != nil

See the online Swift demo

Also, using NSPredicate with MATCHES is an alternative here:

The left hand expression equals the right hand expression using a regex-style comparison according to ICU v3 (for more details see the ICU User Guide for Regular Expressions).

MATCHES actually anchors the regex match both at the start and end of the string (note this might not work in all Swift 3 builds):

let pattern = "\\d{3}-\\d{3}-\\d{3}"
let predicate = NSPredicate(format: "self MATCHES [c] %@", pattern)
let result = predicate.evaluate(with: "123-456-789") 
Sign up to request clarification or add additional context in comments.

Comments

7

What you are looking for is range(of:options:range:locale:) then you can then compare the result of range(of:option:) with whole range of comparing string..

Example:

let phoneNumber = "(999) 555-1111"
let wholeRange = phoneNumber.startIndex..<phoneNumber.endIndex
if let match = phoneNumber.range(of: "\\(?\\d{3}\\)?\\s\\d{3}-\\d{4}", options: .regularExpression), wholeRange == match {
    print("Valid number")
}
else {
    print("Invalid number")
}
//Valid number

Edit: You can also use NSPredicate and compare your string with evaluate(with:) method of its.

let pattern = "^\\(?\\d{3}\\)?\\s\\d{3}-\\d{4}$"
let predicate = NSPredicate(format: "self MATCHES [c] %@", pattern)
if predicate.evaluate(with: "(888) 555-1111") {
    print("Valid")
}
else {
    print("Invalid")
}

9 Comments

I think "\\(?\\d{3}\\)?\\s\\d{3}-\\d{4}" will also allow partial matches. Add ^ and $ anchors on both sides of the pattern.
@WiktorStribiżew Edited answer
Yeah, I thought about that, too. I think there is still another way, but can't find a way to make NSPredicate work in Swift 3. It is really misfortunate that .anchored only anchors at the string start.
@WiktorStribiżew Thanks for remind me about NSPredicate, edited answer with that also
No, it is not the only issue. Mabe the NSPredicate was not ready in Swift 3.0.2.
|
0

Swift extract regex matches

with little bit of edit

import Foundation

func matches(for regex: String, in text: String) -> Bool {
    do {
        let regex = try NSRegularExpression(pattern: regex)
        let nsString = text as NSString
        let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
        return !results.isEmpty
    } catch let error {
        print("invalid regex: \(error.localizedDescription)")
        return false
    }
}

Example usage from link above:

let string = "19320"
let matched = matches(for: "^[1-9]\\d*$", in: string)
print(matched) // will match

let string = "a19320"
let matched = matches(for: "^[1-9]\\d*$", in: string)
print(matched) // will not match

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.