You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
RegEx
RegEx
is a thin
NSRegularExpression
wrapper for easier regular expression testing, data extraction, and replacement in Swift.
Features
Test if a string matches the expression with
test()
Determine the number of matches in a string with
numberOfMatches(in:)
Retrieve all matches in a string with
matches(in:)
Retrieve the first match without processing all matches with
firstMatch(in:)
Efficiently
iterate over matches
with
iterator()
and
next()
Replace matches with a template (including capture groups)
Replace matches one by one with
custom replacement logic
in a closure
The resulting
Match
structure contains the
full match
, any
captured groups
, and corresponding
Swift
string ranges
.
By using
Range<String.Index>
and
Substring
,
RegEx.Match
is able to return all this information without
duplicating data from the input string 👏
Usage
Given a string:
let str ="16^32=2^128"
Define an expression, for example to identify exponent notation (
^
) while
capturing exponent values:
let expression ="\\d+\\^(\\d+)"
Use the regular expression:
let regex =tryRegEx(pattern: expression)
regex.test(str) // true
regex.numberOfMatches(in: str) // 2let first = regex.firstMatch(in: str) // 1 match with 1 captured groupfirst?.values// ["16^32", "32"] let matches = regex.matches(in: str) // 2 matches with 1 captured group eachmatches[0].values// ["16^32", "32"] matches[1].values// ["2^128", "128"]
Iterate over matches
let iterator = regex.iterator(for: str) // Iterate over matches one by oneiterator.next()?.values// ["16^32", "32"] iterator.next()?.values// ["2^128", "128"]iterator.next() // nil
Replacement with Template
let regex =tryRegEx(pattern: #"(\d)(\d)"#)
let result = regex.replaceMatches(in: "1234", withTemplate: "$2$1")
// result: 2143
Replacement with Custom Logic
let regex =tryRegEx(pattern: #"(\w+)\b"#)
let result = regex.replaceMatches(in: "Hello world!") { match inlet value =String(match.values[0] ??"")
returnString(value.reversed())
// result: olleH dlrow!
Installation
No frameworks, just copy and paste!
publicclassRegEx {
privatelet regex: NSRegularExpression
publicinit(pattern: String, options: NSRegularExpression.Options = []) throws {
regex =tryNSRegularExpression(pattern: pattern, options: options)
publicstructMatch {
publiclet values: [Substring?]
publiclet ranges: [Range<String.Index>?]
publicfuncnumberOfMatches(instring: String, fromindex: String.Index?=nil) ->Int {
let startIndex = index ?? string.startIndexlet range =NSRange(startIndex..., in: string)
return regex.numberOfMatches(in: string, range: range)
publicfuncfirstMatch(instring: String, fromindex: String.Index?=nil) -> Match? {
let startIndex = index ?? string.startIndexlet range =NSRange(startIndex..., in: string)
let result = regex.firstMatch(in: string, range: range)
return result.flatMap { map(result: $0, in: string) }
publicfuncmatches(instring: String, fromindex: String.Index?=nil) -> [Match] {
let startIndex = index ?? string.startIndexlet range =NSRange(startIndex..., in: string)
let results = regex.matches(in: string, range: range)
return results.map { map(result: $0, in: string) }
publicfunctest(_string: String) ->Bool {
returnfirstMatch(in: string) !=nilfuncmap(result: NSTextCheckingResult, instring: String) -> Match {
let ranges = (0..<result.numberOfRanges).map { index inRange(result.range(at: index), in: string)
let substrings = ranges.map { $0.flatMap { string[$0] }}
returnMatch(values: substrings, ranges: ranges)
extensionRegEx {
publicclassIterator: IteratorProtocol{
let regex: RegEx
let string: Stringvar current: RegEx.Match?init(regex: RegEx, string: String) {
self.regex= regex
self.string= string
current = regex.firstMatch(in: string)
publicfuncnext() -> RegEx.Match? {
defer {
current = current.flatMap {
let index =$0.ranges[0]?.upperBoundreturnself.regex.firstMatch(in: self.string, from: index)
return current
publicfunciterator(forstring: String) ->Iterator {
returnIterator(regex: self, string: string)
Swift Package Manager
Actually, I love unit tests, so I made this repo a Swift package that can be imported and used with
Swift Package Manager.