Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make sure regex matches the entire string with Swift regex

Tags:

regex

swift

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

like image 702
Kamil Sebastian Góralski Avatar asked Apr 28 '17 08:04

Kamil Sebastian Góralski


People also ask

How do you match a whole expression in regex?

To run a “whole words only” search using a regular expression, simply place the word between two word boundaries, as we did with ‹ \bcat\b ›. The first ‹ \b › requires the ‹ c › to occur at the very start of the string, or after a nonword character.

How do you check if a string matches a regex?

Use the test() method to check if a regular expression matches an entire string, e.g. /^hello$/. test(str) . The caret ^ and dollar sign $ match the beginning and end of the string. The test method returns true if the regex matches the entire string, and false otherwise.

What does '$' mean in regex?

$ means "Match the end of the string" (the position after the last character in the string).

Does Swift have regex?

Swift does not have a regular expression class, so you might think you need to use NSRegularExpressions from Objective-c world, however, you would be wrong.


2 Answers

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") 
like image 59
Wiktor Stribiżew Avatar answered Nov 26 '22 14:11

Wiktor Stribiżew


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")
}
like image 42
Nirav D Avatar answered Nov 26 '22 15:11

Nirav D