This code should work:
let string = "~This two~ are *bold text* and different <textcolor> and ~strikethrough~ and _italic (word*)_ ~abc~"
let embedded = ".*?"
let strikeThroughGroupName = "strikethroughGroupName"
let boldGroupName = "boldGroupName"
let colorGroupName = "colorGroupName"
let italicGroupName = "italicGroupName"
let groupNames = [strikeThroughGroupName, boldGroupName, italicGroupName, colorGroupName]
let pattern = "(~(?<\(strikeThroughGroupName)>\(embedded))~)|(<(?<\(colorGroupName)>\(embedded))>)|(_(?<\(italicGroupName)>\(embedded))_)|(\\*(?<\(boldGroupName)>\(embedded))\\*)"
print("Pattern: \(pattern)")
do {
let regex = try NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
matches.forEach { (aMatch) in
if let groupFound = groupNames.first(where: { aMatch.range(withName: $0).location != NSNotFound }),
let range = Range(aMatch.range(withName: groupFound), in: string) {
let textFound = string[range]
print("Found: \(textFound) with effect: \(groupFound) at NSRange: \(aMatch.range(withName: groupFound))")
}
let fullNSRange = aMatch.range
if let fullRange = Range(fullNSRange, in: string) {
let textFound = string[fullRange]
print("Full Text Found: \(textFound)")
}
}
} catch {
print("Regex error: \(error)")
}
Output:
$>Pattern: (~(?<strikethroughGroupName>.*?)~)|(<(?<colorGroupName>.*?)>)|(_(?<italicGroupName>.*?)_)|(\*(?<boldGroupName>.*?)\*)
$>Found: This two with effect: strikethroughGroupName at NSRange: {1, 8}
$>Full Text Found: ~This two~
$>Found: bold text with effect: boldGroupName at NSRange: {16, 9}
$>Full Text Found: *bold text*
$>Found: strikethrough with effect: strikethroughGroupName at NSRange: {59, 13}
$>Full Text Found: ~strikethrough~
$>Found: italic (word*) with effect: italicGroupName at NSRange: {79, 14}
$>Full Text Found: _italic (word*)_
$>Found: abc with effect: strikethroughGroupName at NSRange: {96, 3}
$>Full Text Found: ~abc~
Side Note:
• I used the group naming (that can be used in regex).
It's constructions is (?<groupName>groupToCapture)
.
• I used embedded
as such, for quick testing. It might not cover all the cases. For instance, it doesn't cover the case where there are a change of line in the string
. If it's <text\ncolor>
(there is a break line), it won't match. There, you can use the regex you want to include breaklines if needed.