Capturing all the occurrences of a specific word when is not part of a link

Viewed 274

I'm trying to get with a regex using PCRE2 dialect from an HTML text all the occurrences of the word 'apple'. But excluding when the word apple it's part of a link.
I'm quite a beginner with Regex, probably I'm doing quite a simple mistake.

\bapple\b

So, the following text has to match the first occurrence but not the second and third one.

Lorem ipsum apple sit amet, consectetur <a href="#">apple</a> elit <a href="/test/apple">lorem</a>. 

What am I doing wrong?

5 Answers

In PCRE, you may use this regex:

~(?is)<a .*?</a>(*SKIP)(*F)|\bapple\b~

RegEx Demo

RegEx Details:

  • (?is): Enable ignore case and DOTALL modes
  • <a .*?</a>: Match text from <a to </a> to skip all <a> tage
  • (*SKIP)(*F): together provide a nice alternative of restriction that you cannot have a variable length lookbehind in PCRE regex
  • |: OR
  • \bapple\b: Match word apple

Since PHP regex is PCRE2-based, you can use a (*SKIP)(*F)/(*SKIP)(*FAIL) regex:

/<a(?:\s[^>]*)?>.*?<\/a>(*SKIP)(*F)|\bMatch Me\b/is

See the regex demo.

Details

  • <a - <a or <A (as the i flag is used, the pattern is case insensitive)
  • (?:\s[^>]*)? - an optional occurrence of a whitespace char (\s) and then any zero or more chars other than > (see [^>]*) (this part makes sure we match <a> as well as <a attr=value attr2=value2...> kinds of tags)
  • > - a > char
  • .*? - any zero or more chars, as few as possible (s flag makes . match line break chars, too)
  • <\/a> - </a> or </A>
  • (*SKIP)(*F) - skip the match and go on to look for further matches from the position where the failure occurred
  • | - or
  • \bMatch Me\b - a whole word Match me (not enclosed with letters, digits or _ chars).
Related