Удалось расковырять самому.
https://regex101.com/r/suCdNB/4/
Основываясь на условных подмасках:
php.net/manual/ru/regexp.reference.conditional.php
а именно:
(?(condition)yes-pattern)
(?(condition)yes-pattern|no-pattern)
Наш анализ сводится к такому: «Если выполняется условие "
не содержится
match", мы применяем шаблон
[^>] (который соответствует телу тега
<a
=тело=>
), иначе (
если match присутствует), применяем пустой шаблон (то есть пытаемся найти пустой тег
<a>
)».
Пустые теги
<a>
теоретически возможны (хоть и с точки зрения внедрения ссылки в текст безопасны), а значит наша регулярка не даёт железно 100%-результат. Потому в качестве
no-pattern-а можно дать любую невалидную абракадабру (просто, чтобы её не было найдено).
<(a)(?(?!match)[^>]|false)+>[^<]*</\1>