Regex matching and template replacement operators in Swift
/I just LOVED this Gist from @morion_black, so I thought I would extend it a little bit to be a little more efficient if the same regex is used multiple times AND to support template replacement. Love tuples, love custom operators. Future me is going to be livid at how much I over-used them.
// // Original Playground taken from https://gist.github.com/u10int/a178945a451d48d4c961 // // Extended to include >< to use the regex to apply a replacement template pattern // import Cocoa struct Regex { var pattern: String{ didSet{ updateRegex() } } var expressionOptions: NSRegularExpressionOptions{ didSet{ updateRegex() } } var matchingOptions: NSMatchingOptions var regex : NSRegularExpression? init(pattern: String, expressionOptions: NSRegularExpressionOptions, matchingOptions: NSMatchingOptions) { self.pattern = pattern self.expressionOptions = expressionOptions self.matchingOptions = matchingOptions updateRegex() } init(pattern:String) { self.pattern = pattern expressionOptions = NSRegularExpressionOptions(0) matchingOptions = NSMatchingOptions(0) updateRegex() } mutating func updateRegex(){ regex = NSRegularExpression.regularExpressionWithPattern(pattern, options: expressionOptions, error: nil) } } let r1 = Regex(pattern: "[a-z]") let r2 = Regex(pattern: "[0-9]", expressionOptions: NSRegularExpressionOptions(0), matchingOptions: NSMatchingOptions(0)) operator infix =~ { associativity left precedence 140 } func =~(left: String, right: Regex) -> Bool { let range: NSRange = NSMakeRange(0, countElements(left)) if right.regex { let matches: AnyObject[] = right.regex!.matchesInString(left, options: right.matchingOptions, range: range) return matches.count > 0 } return false } func =~(left: String, right: String) -> Bool { return left =~ Regex(pattern: right) } operator infix >< { associativity left precedence 140 } func >< (left:String, right: (regex:Regex,template:String) ) -> String{ if left =~ right.regex { let range: NSRange = NSMakeRange(0, countElements(left)) if right.regex.regex { return right.regex.regex!.stringByReplacingMatchesInString(left, options: right.regex.matchingOptions, range: range, withTemplate: right.template) } } return left } func >< (left:String, right: (pattern:String,template:String) ) -> String{ return left >< (Regex(pattern: right.pattern),right.template) } "a" =~ r1 "2" =~ r1 "a" =~ r2 "2" =~ r2 "2" =~ "[a-z]" "2" =~ "[0-9]" var iLoveLetters = "a" >< (r1,"$0!!!!") var iHateNumbers = "d" >< (r2,"$0!!!!") "Hello, Objective-C!!" >< ("Objective.C","Swift") "Hello, Objective C!!" >< ("Objective.C","Swift") "Hello, ObjectiveC!!!" >< ("Objective.*C","Swift")