Last active
June 14, 2023 15:55
-
-
Save trszdev/01c68b2cfd70f5a057be3c65dffa07d0 to your computer and use it in GitHub Desktop.
Allows convenient navigation between capture groups for NSRegularExpression
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
public final class RegexGroup: CustomDebugStringConvertible { | |
public internal(set) var subgroups = [RegexGroup]() | |
public internal(set) var value = Substring() | |
func contains(range: Range<String.Index>) -> Bool { | |
return range.lowerBound >= value.startIndex && range.upperBound <= value.endIndex | |
} | |
public var debugDescription: String { "RegexGroup(\(value))" } | |
} | |
extension NSTextCheckingResult { | |
func group(in value: String) -> RegexGroup? { | |
var stack = [RegexGroup]() | |
for i in 0..<numberOfRanges { | |
let nsRange = self.range(at: i) | |
guard nsRange.location != NSNotFound else { continue } | |
let startIndex = value.index(value.startIndex, offsetBy: nsRange.location) | |
let endIndex = value.index(startIndex, offsetBy: nsRange.length) | |
let range = startIndex..<endIndex | |
guard !range.isEmpty else { continue } | |
let group = RegexGroup() | |
group.value = value[range] | |
while var parentGroup = stack.last, !parentGroup.contains(range: range) { | |
stack.popLast() | |
} | |
stack.last?.subgroups.append(group) | |
stack.append(group) | |
} | |
return stack.first | |
} | |
} | |
extension NSRegularExpression { | |
func firstGroup(in string: String) -> RegexGroup? { | |
let stringRange = NSRange(location: 0, length: string.count) | |
return firstMatch(in: string, range: stringRange)?.group(in: string) | |
} | |
func allGroups(in string: String) -> [RegexGroup] { | |
let stringRange = NSRange(location: 0, length: string.count) | |
return matches(in: string, range: stringRange).compactMap { $0.group(in: string) } | |
} | |
} | |
let timePattern = #"((\d{2})((\d{2}))((F)(\d*))?)"# | |
let regex = try! NSRegularExpression(pattern: timePattern) | |
dump(regex.allGroups(in: "1900F-1800")) | |
dump(regex.firstGroup(in: "1234F3")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment