Regex
Advanced regular expressions for Swift
Goals
Regex library was mainly introduced to fulfill the needs of Swift Express – web application server side framework for Swift.
Still we hope it will be useful for everybody else.
Features
- Deep Integration with Swift
-
=~
operator support - Swift Pattern Matching (aka
switch
operator) support
-
- Named groups
- Match checking
- Extraction/Search functions
- Replace functions
- With a pattern
- With custom replacing function
- Splitting with a Regular Expression
- Simple
- With groups
- String extensions
- Supports grapheme clusters
???
Extra
Path to Regex converter is available as a separate library here: PathToRegex
This one allows using path patterns like /folder/*/:file.txt
or /route/:one/:two
to be converted to Regular Expressions and matched against strings.
Getting started
Installation
Package Manager
Add the following dependency to your Package.swift:
.Package(url: "https://github.com/crossroadlabs/Regex.git", majorVersion: 1)
Run swift build
and build your app.
CocoaPods
Add the following to your Podfile:
pod 'CrossroadRegex'
Make sure that you are integrating your dependencies using frameworks: add use_frameworks!
to your Podfile. Then run pod install
.
Carthage
Add the following to your Cartfile:
github "crossroadlabs/Regex"
Run carthage update
and follow the steps as described in Carthage’s README.
Manually
- Download and drop
/Regex
folder in your project. - Congratulations!
Examples
Hello Regex:
All the lines below are identical and represent simple matching. All operators and matches
function return Bool
//operator way, can match either regex or string containing pattern
"l321321alala" =~ "(.+?)([123]*)(.*)".r
"l321321alala" =~ "(.+?)([123]*)(.*)"
//similar function
"(.+?)([123]*)(.*)".r!.matches("l321321alala")
Operator !~
returns true
if expression does NOT match:
"l321321alala" !~ "(.+?)([123]*)(.*)".r
"l321321alala" !~ "(.+?)([123]*)(.*)"
//both return false
switch
keyword)
Swift Pattern Matching (aka Regex provides very deep integration with Swift and can be used with the switch keyword in the following way:
let letter = "a"
let digit = "1"
let other = "!"
//you just put your string is a regular Swift's switch to match to regular expressions
switch letter {
//note .r after the string literal of the pattern
case "\\d".r: print("digit")
case "[a-z]".r: print("letter")
default: print("bizarre symbol")
}
switch digit {
case "\\d".r: print("digit")
case "[a-z]".r: print("letter")
default: print("bizarre symbol")
}
switch other {
//note .r after the string literal of the pattern
case "\\d".r: print("digit")
case "[a-z]".r: print("letter")
default: print("bizarre symbol")
}
The output of the code above will be:
letter
digit
bizarre symbol
Accessing groups:
// strings can be converted to regex in Scala style .r property of a string
let digits = "(.+?)([123]*)(.*)".r?.findFirst(in: "l321321alala")?.group(at: 2)
// digits is "321321" here
Named groups:
let regex:RegexType = try Regex(pattern:"(.+?)([123]*)(.*)",
groupNames:"letter", "digits", "rest")
let match = regex.findFirst(in: "l321321alala")
if let match = match {
let letter = match.group(named: "letter")
let digits = match.group(named: "digits")
let rest = match.group(named: "rest")
//do something with extracted data
}
Replace:
let replaced = "(.+?)([123]*)(.*)".r?.replaceAll(in: "l321321alala", with: "$1-$2-$3")
//replaced is "l-321321-alala"
Replace with custom replacer function:
let replaced = "(.+?)([123]+)(.+?)".r?.replaceAll(in: "l321321la321a") { match in
if match.group(at: 1) == "l" {
return nil
} else {
return match.matched.uppercaseString
}
}
//replaced is "l321321lA321A"
Split:
In the following example, split() looks for 0 or more spaces followed by a semicolon followed by 0 or more spaces and, when found, removes the spaces from the string. nameList is the array returned as a result of split().
let names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand"
let nameList = names.split(using: "\\s*;\\s*".r)
//name list contains ["Harry Trump", "Fred Barney", "Helen Rigby", "Bill Abel", "Chris Hand"]
Split with groups:
If separator contains capturing parentheses, matched results are returned in the array.
let myString = "Hello 1 word. Sentence number 2."
let splits = myString.split(using: "(\\d)".r)
//splits contains ["Hello ", "1", " word. Sentence number ", "2", "."]
Changelog
You can view the CHANGELOG as a separate document here.
Contributing
To get started, sign the Contributor License Agreement.