Regex недостаточно мощен для анализа HTML (или XML). Любое регулярное выражение, которое вы можете придумать, не будет соответствовать различным формулировкам даже действительного HTML (не говоря уже о реальном теговом супе).
Это проблема с вложенностью. Обычно Regex вообще не может обрабатывать вложение, но Perl имеет нестандартное расширение для поддержки рекурсии regex: (? N), где n - номер группы, в которую нужно вернуться. Итак, что-то вроде этого будет соответствовать обоим пролетам в вашем примере:
(<span[^>]*>.*+(?1)?.*+<\/span>)
См. perlfaq 6.11 .
К сожалению, этого по-прежнему недостаточно, поскольку он должен иметь возможность подсчитывать как приписанные, так и неназначенные начальные теги, позволяя конечному тегу закрывать любой из них. Я не могу придумать, как это можно сделать, не сопоставляя атрибуты start-tag.
Для этого вам нужен HTML-анализатор, и вы все равно должны его использовать, потому что регулярное выражение для HTML / XML - определенно неправильная вещь.