Regex
Pattern match like a boss.
Usage
Create:
// Use `Regex.init(_:)` to build a regex from a static pattern
let greeting = Regex("hello (world|universe)")
// Use `Regex.init(string:)` to construct a regex from dynamic data, and
// gracefully handle invalid input
var validations: [String: Regex]
for (name, pattern) in config.loadValidations() {
do {
validations[name] = try Regex(string: pattern)
} catch {
print("error building validation \(name): \(error)")
}
}
Match:
if greeting.matches("hello universe!") {
print("wow, you're friendly!")
}
Pattern match:
switch someTextFromTheInternet {
case Regex("DROP DATABASE (.+)"):
// TODO: patch security hole
default:
break
}
Capture:
let greeting = Regex("hello (world|universe|swift)")
if let subject = greeting.firstMatch(in: "hello swift")?.captures[0] {
print("ohai \(subject)")
}
Find and replace:
"hello world".replacingFirst(matching: "h(ello) (\\w+)", with: "H$1, $2!")
// "Hello, world!"
Accessing the last match:
switch text {
case Regex("hello (\\w+)"):
if let friend = Regex.lastMatch?.captures[0] {
print("lovely to meet you, \(friend)!")
}
case Regex("goodbye (\\w+)"):
if let traitor = Regex.lastMatch?.captures[0] {
print("so sorry to see you go, \(traitor)!")
}
default:
break
}
Options:
let totallyUniqueExamples = Regex("^(hello|foo).*$", options: [.ignoreCase, .anchorsMatchLines])
let multilineText = "hello world\ngoodbye world\nFOOBAR\n"
let matchingLines = totallyUniqueExamples.allMatches(in: multilineText).map { $0.matchedString }
// ["hello world", "FOOBAR"]
Decode:
let json = """
[
{
"name" : "greeting",
"pattern" : "^(\\\\w+) world!$"
}
]
""".data(using: .utf8)!
struct Validation: Codable {
var name: String
var pattern: Regex
}
let decoder = JSONDecoder()
try decoder.decode(Validation.self, from: json)
// Validation(name: "greeting", pattern: /^(\w+) world!/)
Ranges:
let lyrics = """
So it's gonna be forever
Or it's gonna go down in flames
"""
let possibleEndings = Regex("it's gonna (.+)")
.allMatches(in: lyrics)
.flatMap { $0.captureRanges[0] }
.map { lyrics[$0] }
// it's gonna: ["be forever", "go down in flames"]
Installation
Regex supports Swift 4.2 and above, on all Swift platforms.
Swift Package Manager
Add a dependency to your Package.swift
:
let package = Package(
name: "MyPackage",
dependencies: [
// other dependencies...
.package(url: "https://github.com/sharplet/Regex.git", from: "2.1.0"),
]
)
Carthage
Put this in your Cartfile:
github "sharplet/Regex" ~> 2.1
CocoaPods
Put this in your Podfile:
pod "STRegex", "~> 2.1"
Contributing
See CONTRIBUTING.md.
Development Setup
Swift Package Manager
Build and run the tests:
swift test
# or just
rake test:package
If you're on a Mac, testing on Linux is supported via Docker for Mac. Once Docker is set up, start a Linux shell:
rake docker
And run the tests via Swift Package Manager.
Xcode
xcpretty
is recommended, for prettifying test output:
gem install xcpretty
Then run the tests:
# one of
rake test:osx
rake test:ios
rake test:tvos
Formatting & Linting
Regex uses SwiftFormat to maintain consistent code formatting.
Regex uses SwiftLint to validate code style. SwiftLint is automatically run against pull requests using Hound CI.
When submitting a pull request, running these tools and addressing any issues is much appreciated!
brew bundle
swiftformat .
swiftlint
License
See LICENSE.txt.