4

I have to parse a string, formatted as!info1!info2!, and info2 is optional.

I am trying to capture, using a regular expression, info1 and info2 if needed.

I came up with the following pattern:

!([^!]*?)!(.*?)!|!(.*?)! 

It works, but I am not satisfied with the results:

!foo!bar! -> Group1: foo Group2:bar
!foo!     -> Group3: foo
(https://regex101.com/r/D9d6YP/1)

In both expression, foo means the same thing, and is to be process in the same way afterwards. I would like to capture it in the same group, whether or not there is a second group.

I have tried to use named capture groups, but it seems like they can't be reused

!(?<info1>[^!]*?)!(?<info2>.*?)!|!(?<info1>.*?)!

fails with the error message 'a sub-pattern name must be unique.

Is there any way to capture different patterns in the same group?

Sebastian Proske
  • 7,985
  • 2
  • 26
  • 36
Maxime
  • 1,105
  • 1
  • 10
  • 20

1 Answers1

1

You may use an optional non-capturing group to merge both alternatives into a single branch:

!([^!]*)!(?:([^!]*)!)?
         ^^^        ^^

See the regex demo

Details:

  • ! - a !
  • ([^!]*) - Group 1: any 0+ chars other than !
  • ! - a !
  • (?:([^!]*)!)? - an optional non-capturing group (its result is not stored in memory, no ID is assigned to it) matching 1 or 0 occurrences of
    • ([^!]*) - Group 2: any 0+ chars other than !
    • ! - a !
Wiktor Stribiżew
  • 484,719
  • 26
  • 302
  • 397
  • The pasted code is different from the Regex Demo, demo has \n. I hope the regex101 site is up for ever. – Clown Man Sep 20 '18 at 17:50
  • @ClownMan Of course it is different. It is not a *proof* the regex works, it showcases how the regex will behave with real life strings. When you use the regex in C#, they are *stand-alone*, while in the regex demo, I use a *single multiline* string. Since `[^!]` matches any char but `!`, it matches a newline, and confuses a person who tests the regex against the *lines*. – Wiktor Stribiżew Sep 20 '18 at 17:52