2

I am trying to achieve a regex to select (%?[fFsmhd]){1,} preceded by + and not by \+.

My first option was (?<=[^\\]\+)(%?[fFsmhd]){1,} which seems to work except that the position 1 is never matched.

Test:

+fFsmhd (problem here, does not match)
+fFsmhd (matches)

A workaround I found to this problem is to replace the [^\\] for a nested negated lookbehind ending up with this disgusting thing: (?<=(?<!\\)\+)(%?[fFsmhd]){1,}

Test:

+fFsmhd (matches)
+fFsmhd (matches)

Is there any better way to achieve this without nest lookbehinds to do a simple [^\\]?

Pakoco
  • 163
  • 6

1 Answers1

1

Without lookarounds it is not quite possible to do what you want. Actually, you have a flaw in the pattern: if there is a literal \ before +, it won't get matched. You need to account for any amount of double backslashes:

(?<=(?<!\\)(?:\\{2})*\+)(%?[fFsmhd])+

See this .NET regex demo.

The (?<=(?<!\\)(?:\\{2})*\+) lookbehind requires a + immediately on the left that is not immediately preceded with \ and then any amount of double backslashes.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Woah, such a good correction, thank you very much. I don't get what (?:\\{2}) does, but I am sure with a bit of Googling I can get it easy. – Pakoco May 29 '21 at 06:40
  • @Pakoco `(?:\\{2})*` is a [non-capturing group](https://stackoverflow.com/questions/3512471/what-is-a-non-capturing-group-in-regular-expressions) that matches two backslashes zero or more times. Note you may achieve what you want using one lookaround and a capturing group: `(?<!\\)(?:\\{2})*\+((?:%?[fFsmhd])+)`. The [text you need](http://regexstorm.net/tester?p=%28%3f%3c!%5c%5c%29%28%3f%3a%5c%5c%7b2%7d%29*%5c%2b%28%28%3f%3a%25%3f%5bfFsmhd%5d%29%2b%29&i=%2bfFsmhd+%2bfFsmhd++%5c%5c%5c%2bfFsmhd++%5c%5c%2bfFsmhd++%5c%2bfFsmhd+) is in Group 1. – Wiktor Stribiżew May 29 '21 at 06:46