Swift
regex
string manipulation
programming
code examples

Swift extract regex matches

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Swift, the classic way to extract regex matches is NSRegularExpression. The main detail to get right is that the regex engine uses NSRange, while Swift strings use their own Unicode-aware index model, so safe range conversion is part of the job.

Basic Match Extraction with NSRegularExpression

A straightforward example looks like this:

swift
1import Foundation
2
3let text = "Order 123, invoice 456"
4let pattern = #"\d+"#
5
6let regex = try NSRegularExpression(pattern: pattern)
7let range = NSRange(text.startIndex..., in: text)
8let matches = regex.matches(in: text, range: range)
9
10for match in matches {
11    if let swiftRange = Range(match.range, in: text) {
12        print(String(text[swiftRange]))
13    }
14}

This prints the matched numeric substrings. The important step is converting match.range into a Swift range before slicing the string.

Why the Range Conversion Matters

Swift strings are Unicode-correct and do not use plain integer indexing. NSRegularExpression, however, is a Foundation API based on NSRange, which uses UTF-16 offsets.

That means this conversion is not optional ceremony:

swift
Range(match.range, in: text)

It is the safe bridge between Foundation regex results and Swift string slicing.

Extract Capture Groups

Many regex tasks are really about groups rather than the full match.

swift
1import Foundation
2
3let text = "name=alice age=30"
4let pattern = #"name=(\w+) age=(\d+)"#
5let regex = try NSRegularExpression(pattern: pattern)
6let range = NSRange(text.startIndex..., in: text)
7
8if let match = regex.firstMatch(in: text, range: range) {
9    for groupIndex in 1..<match.numberOfRanges {
10        let nsRange = match.range(at: groupIndex)
11        if let swiftRange = Range(nsRange, in: text) {
12            print(String(text[swiftRange]))
13        }
14    }
15}

Remember that group 0 is the full match, and group 1 onward are your explicit capture groups.

Wrap It in a Helper

If you do this often, a helper function makes the code much cleaner.

swift
1import Foundation
2
3func regexMatches(pattern: String, in text: String) throws -> [String] {
4    let regex = try NSRegularExpression(pattern: pattern)
5    let range = NSRange(text.startIndex..., in: text)
6
7    return regex.matches(in: text, range: range).compactMap { match in
8        guard let swiftRange = Range(match.range, in: text) else {
9            return nil
10        }
11        return String(text[swiftRange])
12    }
13}
14
15let results = try regexMatches(pattern: #"\w+"#, in: "Swift regex demo")
16print(results)

This keeps the Foundation bridging details out of your calling code.

Extracting Specific Groups with a Helper

You can also build a helper that returns captured groups.

swift
1import Foundation
2
3func regexGroups(pattern: String, in text: String) throws -> [[String]] {
4    let regex = try NSRegularExpression(pattern: pattern)
5    let range = NSRange(text.startIndex..., in: text)
6
7    return regex.matches(in: text, range: range).map { match in
8        (1..<match.numberOfRanges).compactMap { index in
9            guard let swiftRange = Range(match.range(at: index), in: text) else {
10                return nil
11            }
12            return String(text[swiftRange])
13        }
14    }
15}

This is useful when you want structured extracted data instead of only the matched surface text.

Newer Swift Regex APIs Exist Too

Modern Swift also includes native regex features, but NSRegularExpression remains common in real codebases because it is widely available, interoperates with Foundation easily, and shows up in older projects.

So even if you later adopt newer regex syntax, understanding the Foundation approach is still practical.

Common Pitfalls

The biggest mistake is trying to use raw NSRange values directly to index a Swift string. That will break because Swift strings are not simple byte arrays.

Another issue is forgetting that capture group 0 is the entire match, not the first explicit captured value.

Developers also recompile the same regex repeatedly in hot paths instead of creating it once and reusing it.

Finally, do not blame the extraction logic when the real problem is an overly broad or poorly anchored regex pattern.

Summary

  • 'NSRegularExpression is a standard way to extract regex matches in Swift.'
  • Convert NSRange results into Swift ranges before slicing strings.
  • Use capture groups when you need subparts of a match.
  • Wrap common regex extraction patterns in helper functions for readability.
  • Keep the regex pattern itself disciplined, because extraction quality depends on it.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.