A
A
Alexey Burlaka2017-05-22 19:31:36
PHP
Alexey Burlaka, 2017-05-22 19:31:36

How to properly use negation in regular expressions?

Good afternoon!
Can you tell me how to properly set up a regular expression?
There is a line:

$str= '
текст 1
<a class="btn" href="https://site.ru/">Ссылка1</a>
текст 2
<a href="https://match.com/">Ссылка2</a>
текст 3
<a class="btn" href="https://fall.com/">Ссылка3</a>
текст 4';

Selects work correctly :
Remove all references that contain a class :
echo preg_replace( '~<(a)[^>]class[^>]*>~siu', "", $str );

Remove all references that do not contain a class :
echo preg_replace( '~<(a)[^>](?!class)[^>]*>~siu', "", $str );

I move inside the tag .
Successfully removes all links that point to a site that contains match in its name :
echo preg_replace( '~<(a)[^>]*?match[^>]+>[^<]+<\/\1>~siu', "", $str );

But the reverse task: to remove all links that do not contain match , I can’t (all tags are cleaned).
Similarly: the working selection from the first example stops working as soon as I add the modifier * or +
<(a)[^>]class[^>]*>
<(a)[^>] + class[^>]*
> how to do it right?
https://regex101.com/r/suCdNB/2

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexey Burlaka, 2017-05-23
@AlexeyGfi

Managed to crack it myself.
https://regex101.com/r/suCdNB/4/
Based on conditional subpatterns:
php.net/manual/ru/regexp.reference.conditional.php
namely:

(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)

Our analysis boils down to this: "If the condition " does not contain a match " is true, we apply the pattern [^>] (which matches the tag <abody =body=> ), otherwise ( if match is present ), we apply an empty pattern (that is, we try to find an empty tag <a>)".
Empty tags <a>are theoretically possible (although they are safe from the point of view of embedding links in the text), which means that our regular expression does not give a 100% result. Therefore, any invalid abracadabra can be given as a no-pattern (just so that it is not found).
<(a)(?(?!match)[^>]|false)+>[^<]*</\1>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question