6

I have the following string: "@[1484987415095898:274:Page Four]" and I want to capture the name, so I wrote to following regexp @\[[\d]+:[\d]+:(.*)] It seems to be working, but now I am struggling to understand how to replace the previous string with the capture group one.
i.e
"Lorem ipsum @[1484987415095898:274:Page Four] dolores" ->
"Lorem ipsum Page Four dolores"

Note, I saw how to get the capture group out using this stack question however, how to I find the original string this was extracted from and replace it?

Yoav Schwartz
  • 2,017
  • 2
  • 23
  • 43
  • 1
    Possible duplicate of [Swift 3 - How do I extract captured groups in regular expressions?](https://stackoverflow.com/questions/42789953/swift-3-how-do-i-extract-captured-groups-in-regular-expressions) – Tamás Sengel Sep 10 '17 at 20:47
  • It is not about extracting groups here, but about how to replace with them. – Wiktor Stribiżew Oct 01 '17 at 19:57

1 Answers1

9

You need to replace the whole match with the $1 replacement backreference that holds the contents captured with the first capturing group.

Besides, I'd advise to write the [\d] as \d to avoid misinterpretations of the character class unions if you decide to expand the pattern later. Also, it is safer to use .*?, lazy dot matching, to get to the first ] rather than to the last ] (if you use .* greedy variation). However, that depends on the real requirements.

Use either of the following:

let txt = "Lorem ipsum @[1484987415095898:274:Page Four] dolores"
let regex = NSRegularExpression(pattern: "@\\[\\d+:\\d+:(.*?)\\]", options:nil, error: nil)
let newString = regex!.stringByReplacingMatchesInString(txt, options: nil, range: NSMakeRange(0, count(txt)), withTemplate: "$1")
print(newString)
// => Lorem ipsum Page Four dolores

or

let txt = "Lorem ipsum @[1484987415095898:274:Page Four] dolores"
let newString = txt.replacingOccurrences(of: "@\\[\\d+:\\d+:(.*?)]", with: "$1", options: .regularExpression)
print(newString)
// => Lorem ipsum Page Four dolores
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    Or simply `let newString = txt.replacingOccurrences(of: "@\\[[\\d]+:[\\d]+:(.*)]", with: "$1", options: .regularExpression)` – rmaddy Sep 10 '17 at 21:07
  • @rmaddy Yeah, that is a better notation, thanks. I still prefer my pattern that is cleaner and should be safer in case there are several matches on the same line. – Wiktor Stribiżew Sep 10 '17 at 21:12
  • If you prefer your use of `NSRegularExpression` (which has many benefits), then why change your answer? – rmaddy Sep 10 '17 at 21:13
  • @rmaddy I thought you criticized my notation :) – Wiktor Stribiżew Sep 10 '17 at 21:14
  • Not at all. I was simply pointing out an alternate approach. Your use of `NSRegularExpression` has it's benefits. My suggestion is good if it's a one-time use. – rmaddy Sep 10 '17 at 21:16
  • Which one would work if there could be more than one occasion of the regular expression in the string? "Lorem ipsum @[1484987415095898:274:Page Four] dolores @[1484987415095898:274:Page Six] " – Yoav Schwartz Sep 10 '17 at 21:25
  • Both approaches are basically the same and both will replace all occurrences. BTW - another option to replacing the `.*` with `.*?` is to replace the `.*` with `[^]]*`. – rmaddy Sep 10 '17 at 21:51
  • @rmaddy I am biased in this specific case to use `.*?`: 1) the `]` inside the character class must be escaped in ICU regex flavor and overescaping makes a pattern difficult to read, 2) If OP needs to precise the context of the trailing `]`, the `[^]]` will turn out too restrictive. – Wiktor Stribiżew Sep 10 '17 at 21:57
  • @YoavSchwartz These 2 snippets are equivalent in your scenario. – Wiktor Stribiżew Sep 10 '17 at 21:57
  • Thank you guys. It seems I always get close with the Regex but it's never the right one :) Thanks for your help! – Yoav Schwartz Sep 11 '17 at 06:55