Search code examples
regexregex-group

Regex with optional groups not working - \d is not working in the parenthesis (\d*%)


I need to write regex for the following rules in which button (a,b,start) are the only field required, all other groups are optional but having problems. Some look-behind logic is also required which I am having problem with as well

  • This regex is for a virtual game controller with buttons. Some of the buttons are "a", "b," and "start".
  • Each button can have a duration appended, but it is not required. "a500ms" will press the A button for 500 milliseconds. "a1s" will press the A button for 1 second.
  • Buttons can be pressed in sequence without spaces. "ab" presses A then B. "astart" presses A then Start.
  • The parser syntax is as follows: (modifier) (button) (percentage) (percent symbol) (duration) (duration type) (appended)
  • (button) is the only required group. Everything else is optional.
  • If (percent symbol) does not have a (percentage) or (duration type) does not have a (duration), it's invalid
  • A complete example utilizing the full syntax: "_start20%12ms+"
  • This holds "start" for 20 percent for 12 milliseconds and appends a later input

Examples:

  • "a600msb200ms" - valid
  • "ams500b" - invalid since (duration type) ("ms") did not have (duration) ("500") before it
  • "astart" - presses A then Start (this currently does not work in my regex, but it should)
  • "b1sstart" - presses B for 1 second then start
  • "b+a" - presses B and A simultaneously
  • "_b a" - holds B then presses A

My regexp:

^(a|b|start)(\d*%)?(\d*(s|ms))?

Here is the test bed https://regex101.com/r/jGf0VR/3

Problems

The regex is not working for me with the following problems

  1. (\d*%)? - this group is not working, suppose to capture 500%, 200% but it is not working (yes tried it with backslash still does not work). The fact it should be optional but it is never taken as optional

  2. a200ms300s - should be captured but it is not captured, similarly a200s300msshould also be captured

  3. a200ms200% - should be invalid, I can't seem to fix this one primarily because of (\d*%)? is not working for me as highlighted in prob1


Solution

  • Use the following to match a string containing a single button press:

    ^(a|b|start)(\d+%)?(\d+(s|ms))?$
    

    I changed \d* to \d+ to indicate that at least one digit is required before % or s|ms. I added $ at the end so it won't match if there's something extra after the match.

    To match a sequence of them, put a group around everything except the anchors, and allow it to repeat.

    ^((a|b|start)(\d+%)?(\d+(s|ms))?)+$
    

    DEMO