Created
July 31, 2019 13:46
-
-
Save AliSoftware/96847470ae62489c7043cb0a098d1491 to your computer and use it in GitHub Desktop.
Simple wrapper around NSRegularExpression to provide a swiftier API and, ability to have matches exposing Range instead of NSRange
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
// Simple wrapper around NSRegularExpression to provide a swiftier API and, ability to have matches exposing Range instead of NSRange | |
import Foundation | |
struct RegEx { | |
let regex: NSRegularExpression | |
init(pattern: String, options: NSRegularExpression.Options = []) throws { | |
self.regex = try NSRegularExpression(pattern: pattern, options: options) | |
} | |
struct Match { | |
let fullString: String | |
let result: NSTextCheckingResult | |
var range: Range<String.Index> { | |
return self.range(at: 0) | |
} | |
var text: Substring { | |
return fullString[range] | |
} | |
var numberOfRanges: Int { | |
return result.numberOfRanges | |
} | |
func range(at index: Int) -> Range<String.Index> { | |
return Range(result.range(at: index), in: fullString)! | |
} | |
func range(named name: String) -> Range<String.Index> { | |
return Range(result.range(withName: name), in: fullString)! | |
} | |
subscript(index: Int) -> Substring { | |
return fullString[self.range(at: index)] | |
} | |
subscript(name: String) -> Substring { | |
return fullString[self.range(named: name)] | |
} | |
} | |
func matches(in string: String, options: NSRegularExpression.MatchingOptions = []) -> [Match] { | |
let nsrange = NSRange(string.startIndex... , in: string) | |
let results = self.regex.matches(in: string, options: options, range: nsrange) | |
return results.map { match in | |
Match(fullString: string, result: match) | |
} | |
} | |
} | |
extension RegEx: ExpressibleByStringLiteral { | |
init(stringLiteral value: String) { | |
try! self.init(pattern: value) | |
} | |
} | |
extension RegEx.Match: CustomStringConvertible { | |
var description: String { | |
return String(self.text) | |
} | |
} | |
extension RegEx.Match: CustomDebugStringConvertible { | |
var debugDescription: String { | |
let submatches: [String] = (0..<self.numberOfRanges).map { | |
let range = self.range(at: $0) | |
let start = fullString.distance(from: fullString.startIndex, to: range.lowerBound) | |
let end = fullString.distance(from: fullString.startIndex, to: range.upperBound) | |
return " - [\($0)]: [\(start)...\(end)] = \"\(self[$0])\"" | |
} | |
return "RegEx.Match \"\(text)\"\n" + submatches.joined(separator: "\n") | |
} | |
} | |
//: ## Example usage | |
let list = "#Q23AS9D0APQQ2 Q23AS9D0APQQ2 #111111 #aaaaaa #q2IasK231@!@!#_+123 #asdas12312...1231@asda___213-1 #asdas123121231asda2131 asdas123121231asda2131" | |
let re = try! RegEx(pattern: #"#[a-z][a-z0-9]*\b"#, options: .caseInsensitive) | |
let results = re.matches(in: list) | |
results.forEach { print($0.debugDescription) } | |
/* | |
RegEx.Match "#Q23AS9D0APQQ2" | |
- [0]: [0...14] = "#Q23AS9D0APQQ2" | |
RegEx.Match "#aaaaaa" | |
- [0]: [37...44] = "#aaaaaa" | |
RegEx.Match "#q2IasK231" | |
- [0]: [45...55] = "#q2IasK231" | |
RegEx.Match "#asdas12312" | |
- [0]: [66...77] = "#asdas12312" | |
RegEx.Match "#asdas123121231asda2131" | |
- [0]: [98...121] = "#asdas123121231asda2131" | |
*/ | |
print(results.map { $0.text }) | |
/* | |
["#Q23AS9D0APQQ2", "#aaaaaa", "#q2IasK231", "#asdas12312", "#asdas123121231asda2131"] | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment