Одиночное регулярное выражение perl для удаления экранированных амперсандов из атрибутов href, но не где-либо еще - PullRequest
1 голос
/ 19 мая 2009

Это больше вопрос головоломки для моего любопытства, чем что-либо еще. Я ищу одну замену регулярного выражения, которая преобразует амперсанды, экранированные от сущностей, в неэкранированные амперсанды только в атрибутах href в html-файле. Например:

<a href="http://example.com/index.html?foo=bar&amp;baz=qux&amp;frotz=frobnitz">
Me, myself &amp; I</a>

Будет преобразовано в:

<a href="http://example.com/index.html?foo=bar&baz=qux&frotz=frobnitz">
Me, myself &amp; I</a>

Теперь я могу сделать это в нескольких утверждениях, но мне любопытно, может ли любой гуру Perl Regex сделать это в одном.

Самое близкое, что я дошел, это следующее регулярное выражение, которое не работает, потому что взгляды не могут быть переменной длины. Конечно, это может не сработать, даже если им позволят, я не уверен.

s/(?<=href=".*?)&amp;(?=.*?")/&/g;

Спасибо.

Ответы [ 4 ]

3 голосов
/ 19 мая 2009

Адаптация вашего близкого приближения:

while (s/(?<=href=")([^"]*?)&amp;/$1&/) {}

Это чит; но это единственное регулярное выражение. Ключевой частью является сканирование нежадных символов, которые не являются закрывающей двойной кавычкой, за которой следует строка &amp;. Другое наблюдение, которое следует сделать, это с учетом ввода:

<a href="http://example.com/index.html?x=y&amp;amp;amp;y=z">

Вы выйдете:

<a href="http://example.com/index.html?x=y&y=z">

Вы должны решить, имеет ли это значение.

Сложность любого неитеративного решения заключается в том, что, прочитав 'href="' в первом совпадении, вы больше не увидите его для последующих совпадений.

2 голосов
/ 01 июля 2009

Это регулярное выражение будет делать то, что вы хотите в одной строке кода Perl, без неэффективного цикла while (который заставляет регулярное выражение начинаться каждый раз с начала) или без просмотра:

s/((href="|\G)[^"]*?&)amp;/$1/g;

Хитрость заключается в том, чтобы использовать \ G, чтобы регулярное выражение "помнило", что оно было внутри атрибута href.

Это регулярное выражение также правильно заменяет & amp; с & amp;

Единственный недостаток в том, что если & произойдет в самом начале строки темы, она также будет заменена. Если вы хотите избежать этого, используйте:

s/((href="|\G(?!\A))[^"]*?&)amp;/$1/g;
1 голос
/ 01 июля 2009

OK. Прежде всего - & amp; в hrefs это прекрасно, поэтому я не понимаю, почему вы хотите изменить его - на самом деле HTML с & in hrefs не будет действительным!

Во-вторых - если вам это нужно для чего-то - вам действительно следует использовать какой-то разумный HTML-парсер.

Третье, что вы хотите, может быть сделано довольно легко, но не очень красиво:

s{href="([^"]*)"}{my $q=$1; $q =~ s/\&amp;/&/g; 'href="' . $q . '"'}eg;

Но, пожалуйста: тот факт, что это технически возможно, не означает, что вы должны его использовать.

1 голос
/ 19 мая 2009

Не пытайтесь анализировать нерегулярные языки с помощью регулярных выражений. Получите анализатор HTML из CPAN, а затем работайте только с нужным элементом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...