Reputation: 748
I am following http://www.raywenderlich.com/86205/nsregularexpression-swift-tutorial and using the playground file below:
http://cdn5.raywenderlich.com/wp-content/uploads/2015/01/iRegex-Playground-Xcode-6.3.zip
to help find matches , but I need to be able to exclude certain results .
Basically I am looking at the following pattern:
let thenotClasses = "*121:32, Malachi 22:66 , 32:434, 16:111 , 17:11 , John 13:14, Verse 41:29, Great 71:21"
listMatches("\\d\\d?\\d?:\\d\\d?\\d?", inString: thenotClasses)
I get all the number:number matches , however, what I really want to do is to also tell it to exclude any matches prefixed with '*' or matches which are preceded by the word "Malachi " or "John " but include the rest
So in this case I want the matches to return:
[32:434, 16:111 , 17:11 , 41:29 and 71:21]
Any help would be greatly appreciated, God willing :)
Upvotes: 0
Views: 852
Reputation: 93171
A RegEx pattern that invalidates a match when preceded by certain words are hard to write, mostly because the regex engine is greedy so it can start with the next digit.
If you use a negative look-behind:
(?<!\*|Malachi |John )(\d+:\d+)
Which means "match digits not preceded by *
, Malachi
or John
" the match will just begin from the next digit. In Malachi 22:66
for example, it will capture 2:66
.
The most common pitfalls I've seen with Regex usage is to delegate everything to the regex engine. It is powerful indeed but you forgot you also have vastly more flexible programming language that calls the regex.
Here's an idea that mixes the two together: capture any number:number
and check what goes before it. Exclude the match if it is preceded by *
or Malachi
or John
.
Pattern:
(\*|Malachi |John )?(\d+:\d+)
(\*|Malachi |John ) - match a *, Malachi or John and put it into capture group 1
? - make the first capture group optional
(\d+:\d+) - match the verse and put it into capture group 2
Code:
let str = "*121:32, Malachi 22:66 , 32:434, 16:111 , 17:11 , John 13:14, Verse 41:29, Great 71:21"
let s = str as NSString // NSString is easier to work with Regex
let regex = try! NSRegularExpression(pattern: "(\\*|Malachi |John )?(\\d+:\\d+)", options: [])
var verses = [String]()
regex.enumerateMatchesInString(str, options: [], range: NSMakeRange(0, str.characters.count)) { result, flags, stop in
// Check that the first capture group is not found. Otherwise, return
guard let result = result where result.rangeAtIndex(1).location == NSNotFound else {
return
}
// When the first capture group is not found, add the second capture, group
// i.e. the verse number, to the result list
verses.append(s.substringWithRange(result.rangeAtIndex(2)))
}
print(verses)
Upvotes: 1