Capture UUID values with regex in Swift
When working with UUIDs in Swift, we may need to match and extract them using regular expressions. To achieve this in a type-safe and reusable way, we can define a custom RegexComponent leveraging the Capture component.
# Defining a reusable RegexComponent for UUIDs
The following implementation creates a CaptureUUID
struct that conforms to RegexComponent
. This struct defines a regular expression pattern for matching UUIDs while ensuring type safety through a transformation function.
import RegexBuilder
struct CaptureUUID: RegexComponent {
let reference: Reference<UUID>
init(as reference: Reference<UUID>) {
self.reference = reference
}
@RegexComponentBuilder
var regex: Regex<(Substring, UUID)> {
Capture(as: reference) {
Repeat(count: 8) { .hexDigit }
"-"
Repeat(count: 4) { .hexDigit }
"-"
Repeat(count: 4) { .hexDigit }
"-"
Repeat(count: 4) { .hexDigit }
"-"
Repeat(count: 12) { .hexDigit }
} transform: { substring in
try Self.transform(substring)
}
}
private static func transform(
_ substring: Substring
) throws -> UUID {
guard
let uuid = UUID(uuidString: String(substring))
else {
throw RegexTransformError
.unableToDecode(UUID.self, from: substring)
}
return uuid
}
}
enum RegexTransformError: Error {
case unableToDecode(Any.Type, from: Substring)
}
# Using CaptureUUID in a regex expression
This component can be integrated into a larger regex pattern to extract UUID values from a given string. For example, the following regex captures a UUID from a URL path:
let accountID = Reference<UUID>()
let regex = Regex {
"accounts/"
CaptureUUID(as: accountID)
"/"
Optionally {
"index.json"
}
Anchor.endOfSubject
}
let match = url
.path(percentEncoded: false)
.firstMatch(of: regex)
if let match {
// Returns the account id as a UUID
return match[accountID]
}
By using CaptureUUID
, we ensure type-safe access to extracted values while improving the clarity and maintainability of our regex-based parsing logic.