Regex return true if even a substring follows the pattern

Viewed 179

I was just practicing regex and found something intriguing

for a string

"world9 a9$ b6$" my regular expression "^(?=.*[\\d])(?=\\S+\\$).{2,}$"

will return false as there is a space in between before the look ahead finds the $ sign with at least one digit and non space character.

As a whole the string doesn't matches the pattern.

What should be the regular expression if I want to return true even if a substring follows a pattern? as in this one a9$ and b6$ both follow the regular expression.

2 Answers

You can use

^(?=\D*\d)(?=.*\S\$).{2,}$

See the regex demo. As The fourth bird mentions, since \S\$ matches two chars, you may simply move the pattern to the consuming part, and use ^(?=\D*\d).*\S\$.*$, see this regex demo.

Details

  • ^ - start of string (implicit if used in .matches())
  • (?=\D*\d) - a positive lookahead that requires zero or more non-digit chars followed with a digit char immediately to the right of the current location
  • (?=.*\S\$) - a positive lookahead that requires zero or more chars other than line break chars, as many as possible, followed with a non-whitespace char and a $ char immediately to the right of the current location
  • .{2,} - any two or more chars other than line break chars, as many as possible
  • $ - end of string (implicit if used in .matches())

Mostly, knock out the ^ and $ bits, as those force this into a full string match, and you want substring matches. In general, look-ahead seems like a mistake here, what are you trying to accomplish by using that? (Look-ahead/look-behind is rarely needed in general). All you need is:

Pattern.compile("\\S+\\$");

possibly, if you want an element (such as a9$) to stand on its own, use \b which is regexpese for word break: Basically, whitespace (and a few other characters, such as underscores. Most non-letter, non-digits characters are considered a break. Think [^a-zA-Z0-9]) - but \b also matches start/end of input. Thus:

Pattern.compile("\\b\\S+\\$\\b")

still matches foo a9$ bar, or a9$ just fine.

If you MUST put this in terms of a full match, e.g. because matches() (which always does a full string match) is run and you can't change that, well, put ^.* in front and .*$ at the back of it, simple as that.

Absolutely nothing about this says "This can only be needed with lookahead".

Related