Swift Regex: Does a String Match a Pattern

Swift regex: does a string match a pattern?

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.

Check string matches exact format swift 5

You need two things:

  • Escape parentheses
  • Add anchors because in the current code, the regex can match a part of a string.

You can thus use

stringToCheck.range(of: #"^\([0-9],[0-9]\)\z"#, options: .regularExpression, range: nil, locale: nil) != nil

Note the # chars on both ends, they allow escaping with single backslashes.

Details:

  • ^ - start of string
  • \( - a ( char
  • [0-9] - a single ASCII digit (add + after ] to match one or more digits)
  • , - a comma
  • [0-9] - a single ASCII digit (add + after ] to match one or more digits)
  • \) - a ) char
  • \z - the very end of string (if linebreaks cannot be present in the string, $ is enough).

Validate if string match with regex

To get the M letter use

import Foundation

let idPassport = "G394968225MEX25012974M2807133<<<<<<06"
let regexGender = "[FM](?=[0-9]{7})"
var genderPassport=""
if let rng = idPassport.range(of: regexGender, options: .regularExpression) {
genderPassport=String(idPassport[rng])
}
print(genderPassport)
// => M

Here, [FM](?=[0-9]{7}) matches F or M that are followed with any seven digits.

How to see if a specific string matches a regex pattern?

Instead of testing whether the range is nil, look to see whether the range is the whole target string.

let string = "5"
let r = string.characters.indices
let pattern = "[0-9]"
let r2 = string.rangeOfString(pattern, options: .RegularExpressionSearch)
if r2 == r { print("match") }

EDIT Someone asked for a translation into Swift 4:

let string = "5"
let r = string.startIndex..<string.endIndex
let pattern = "[0-9]"
let r2 = string.range(of: pattern, options: .regularExpression)
if r2 == r { print("match") }

Use regular expression in Swift String.contains() func

You are quite close

if thisString.range(of: "[^a-zA-Z0-9-]", options: .regularExpression) != nil { 
//reject
} else {
//accept
}

Regular expressions in swift

Separate the string by non alpha numeric characters except white spaces. Then trim the elements with white spaces.

extension String {
func words() -> [String] {
return self.components(separatedBy: CharacterSet.alphanumerics.inverted.subtracting(.whitespaces))
.filter({ !$0.isEmpty })
.map({ $0.trimmingCharacters(in: .whitespaces) })
}
}

let string1 = "(name,john,string for user name)"
let string2 = "(name, john,name of john)"
let string3 = "key = value // comment"

print(string1.words())//["name", "john", "string for user name"]
print(string2.words())//["name", "john", "name of john"]
print(string3.words())//["key", "value", "comment"]

(Swift) How to find all strings that matches regex in string

You would need to manually find all occurrences in your string using a while condition similar to the one used in this post and get the string subsequences instead of its range:

func findSrcs(_ content: String) -> [Substring] {
let pattern = #"(?<=src=")[^"]+"#
var srcs: [Substring] = []
var startIndex = content.startIndex
while let range = content[startIndex...].range(of: pattern, options: .regularExpression) {
srcs.append(content[range])
startIndex = range.upperBound
}
return srcs
}

Playground testing:

let content = """
<span>whatever</span>
<img src="smiley.gif" alt="Smiley face">
<span>whatever</span>
<img src="stackoverflow.jpg" alt="Stack Overflow">
"""

print(findSrcs(content))

This will print

["smiley.gif", "stackoverflow.jpg"]

Swift regex for searching format specifiers in a string

First of all you have to replace the matches reversed otherwise you will run into index trouble.

A possible pattern is

%([.0-9]+)?[@df]

it considers also the (optional) decimal places specifier.

var description = "I am %@. My age is %d and my height is %.02f. (%@)"
let pattern = "%([.0-9]+)?[@df]"
let regex = try NSRegularExpression(pattern: pattern)
let nsrange = NSRange(description.startIndex..., in: description)

for match in regex.matches(in: description, range: nsrange).reversed() {
let range = Range(match.range, in: description)!
description.replaceSubrange(range, with: "MATCH")
}
print(description)

Make sure regex matches the entire string with Swift regex

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")


Related Topics



Leave a reply



Submit