'How to make optional capturing groups be matched first

For example I want to match three values, required text, optional times and id, and the format of id is [id=100000], how can I match data correctly when text contains spaces.

my reg: (?<text>[\s\S]+) (?<times>\d+)? (\[id=(?<id>\d+)])?

example source text: hello world 1 [id=10000]

In this example, all of source text are matched in text



Solution 1:[1]

The problem with your pattern is that matches any whitespace and non whitespace one and unlimited times, which captures everything without getting the other desired capture groups. Also, with a little help with the positive lookahead and alternate (|) , we can make the last 2 capture groups desired optional.

The final pattern (?<text>[a-zA-Z ]+)(?=$|(?<times>\d+)? \[id=(?<id>\d+)])

  • Group text will match any letter and spaces.
  • The lookahead avoid consuming characters and we should match either the string ended, or have a number and [id=number]

Said that, regex101 with further explanation and some examples

Solution 2:[2]

You could use:

:\s*(?<text>[^][:]+?)\s*(?<times>\d+)? \[id=(?<id>\d+)]

Explanation

  • : Match literally
  • \s* Match optional whitespace chars
  • (?<text> Group text
    • [^][:]+? match 1+ occurrences of any char except [ ] :
  • ) Close group text
  • \s* Match optional whitespace chars
  • (?<times>\d+)? Group times, match 1+ digits
  • \[id= Match [id=
  • (?<id>\d+) Group id, match 1+ digirs
  • ] Match literally

Regex demo

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 lucas_7_94
Solution 2 The fourth bird