Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple regex with repeated unordered matches

I have this regex

/^[a-z]{1,}( (?=[a-z])){0,}(_(?=[a-z])){0,}[a-z]{0,}$/

I want to match

ag_b_cf_ajk

or

zva b c de

or

hh_b opxop a_b

so any character tokens separated by a single space or underscore.

(In the regex above, we have a literal space, which is legal, and we have look-aheads that ensure that a space or underscore is followed by a character).

The problem is, my above regex is only matching the first space or underscore, like so:

axz_be
axz be

but these fail

axz_be_j
axz be j

I believe I missing some concept with regexes in order to solve this as I have been trying for the last few hours!

like image 865
Alexander Mills Avatar asked Mar 14 '23 00:03

Alexander Mills


1 Answers

It seems you can just use

^[a-z]+(?:[_ ][a-z]+)*$

See the regex demo

The regex matches

  • ^ - start of string
  • [a-z]+ - one or more lowercase ASCII letters
  • (?:[_ ][a-z]+)* - zero or more sequences of:
    • [_ ] - a space or an underscore
    • [a-z]+ - one or more lowercase ASCII letters
  • $ - end of string

If the space or underscore must appear at least once, use the + quantifier instead of *:

^[a-z]+(?:[_ ][a-z]+)+$
                     ^

To add a multicharacter alternative to the underscore and hyphen, you need to introduce another non-capturing group:

^[a-z]+(?:(?:[_ ]|\[])[a-z]+)+$

See another regex demo

like image 107
Wiktor Stribiżew Avatar answered Mar 18 '23 19:03

Wiktor Stribiżew