Regex Tester — Swift source
Test regular expressions against any text with all flags (g/i/m/s/u/y). See every match, its index and capture groups, plus the constructed pattern. 100% in-browser.
This is the Swift implementation — the same logic the interactive tool runs, in a shareable, citable form.
// regex-tester — Swift port. Match a pattern against text, report every
// match with capture groups and index (NSRegularExpression, ICU engine).
import Foundation
struct RegexMatch {
let match: String
let index: Int
let groups: [String] // "" where a group did not participate
}
enum RegexTester {
// JS flag letters -> NSRegularExpression.Options. g selects all matches;
// u is the default for String; y has no equivalent.
static func compileOptions(_ flags: String) -> NSRegularExpression.Options {
var o: NSRegularExpression.Options = []
if flags.contains("i") { o.insert(.caseInsensitive) }
if flags.contains("m") { o.insert(.anchorsMatchLines) }
if flags.contains("s") { o.insert(.dotMatchesLineSeparators) }
return o
}
static func runRegex(_ pattern: String, _ flags: String,
_ text: String) -> (matches: [RegexMatch], error: String?) {
guard !pattern.isEmpty else { return ([], nil) }
let ns = text as NSString
let full = NSRange(location: 0, length: ns.length)
do {
let re = try NSRegularExpression(pattern: pattern, options: compileOptions(flags))
var found = flags.contains("g")
? re.matches(in: text, options: [], range: full)
: []
if !flags.contains("g"), let m = re.firstMatch(in: text, options: [], range: full) {
found = [m]
}
let matches = found.prefix(2000).map { m -> RegexMatch in
var groups: [String] = []
if m.numberOfRanges > 1 {
for g in 1..<m.numberOfRanges {
let r = m.range(at: g)
groups.append(r.location == NSNotFound ? "" : ns.substring(with: r))
}
}
return RegexMatch(match: ns.substring(with: m.range),
index: m.range.location, groups: groups)
}
return (Array(matches), nil)
} catch let e as NSError {
return ([], e.localizedDescription)
}
}
// Render a result the way the tool's UI does:
// `N. "match" @ index -> [g1, g2]`, or `(none)` when empty.
static func formatMatches(_ result: (matches: [RegexMatch], error: String?)) -> String {
if let err = result.error { return err }
if result.matches.isEmpty { return "(none)" }
return result.matches.enumerated().map { i, m in
var line = "\(i + 1). \"\(m.match)\" @ \(m.index)"
if !m.groups.isEmpty { line += " -> [\(m.groups.joined(separator: ", "))]" }
return line
}.joined(separator: "\n")
}
}
let result = RegexTester.runRegex(#"(\w+)@(\w+)\.(\w+)"#, "g", "mail@x.com nope bob@test.org")
print(RegexTester.formatMatches(result))
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →