RegEx, чтобы удалить все разметки между тегами <a и</a>, кроме как в [и]
Попытка выяснить регулярное выражение дает мне судороги мозга:)
Я заменяю тысячи отдельных ссылок href
с помощью отдельного короткого кода в постсоветском контенте WordPress, используя плагин, который позволяет запускать регулярные выражения для контента.
Вместо того, чтобы пытаться объединить SQL-запрос с RegEx, я делаю это в два этапа: сначала SQL, чтобы найти/заменить каждый отдельный URL-адрес на отдельный короткий код, а второй этап - удалить остальную часть ' href` link.
Вот некоторые примеры того, что у меня есть с первого шага; как вы можете видеть, URL-адрес был заменен коротким кодом [nggallery id=xxx]
.
<a href="[nggallery id=xx]"><span class="shutterset">
<img class="alignnone size-large wp-image-23067" title="Image Title"
src="http://example.com/wp-content/uploads/2015/06/image-title.jpg"
alt="" width="685" height="456" /></span></a>
<a href="[nggallery id=xxxxx]">Click here!</a>
<a title="title title" href="[nggallery id=xxx]" target="_blank">Title Link Title Link</a>
Теперь мне нужно удалить все разметки ссылок href
- span
, img
и т.д. между ведущими <a
и заканчивающимися </a>
, оставив только короткий код [nggallery id=xxx]
.
У меня есть начало здесь: https://www.regex101.com/r/rL8wP1/2
Но я не знаю, как предотвратить использование [nggallery id=xxx]
короткого кода в RegEx.
Обновление 7/09/2015
@nhahtdh ответ, кажется, работает отлично, не слишком жадный и не ест соседние ссылки html. Используйте (
и )
как разделители и $1
в качестве замены плагином regex в WordPress. (Если вы используете BBEdit, вам нужно будет использовать \1
)
( <a\s[^>]*"(\[nggallery[^\]]*\])".*?<\/a> )
Обновление 7/02/2015
Спасибо Fab Sa (ниже), его регулярное выражение https://www.regex101.com/r/rL8wP1/4
<a.*(\[nggallery[^\]+]*\]).*?<\/a>
работает в эмуляторе regex101, но при использовании в текстовом редакторе BBEdit или плагине WordPress, который запускает регулярное выражение, его регулярное выражение удаляет короткий код [nggallery id=***]
. Так это слишком жадно? Некоторые другие проблемы?
Обновление 7/01/2015:
Я знаю, я знаю, re: RegEx сопоставляет открытые теги, кроме XHTML автономных тегов ВЫ НЕ МОЖЕТЕ ПОВТОРИТЬ HTML С REGEX
Ответы
Ответ 1
Fab Sa regex <a.*(\[nggallery[^\]+]*\]).*?<\/a>
копирует все, когда в одной строке есть несколько тегов <a>
, из-за неограниченного .*
в начале, который будет соответствовать различным тегам <a>
.
Ограничивая допустимые символы, вы можете несколько соответствовать тому, что хотите:
<a\s[^>]*"(\[nggallery[^\]]*\])".*?<\/a>
^^^^^^^
Я запустил по крайней мере одну пробел после a
, чтобы убедиться, что он не соответствует некоторым другим тегам, а также некоторым дополнительным ограничениям.
В любом случае, вы сами по себе, если обнаружите, что он не работает в каком-то угловом случае. Это вообще плохая идея манипулировать HTML с регулярным выражением.
Ответ 2
Вы можете использовать это регулярное выражение
<a.*(\[nggallery[^\]+]*\]).*?<\/a>
глобально (флаг g). Это регулярное выражение будет соответствовать ссылке и сохранить часть [nggallery ...]
. Вы можете заменить все совпадение на $1, чтобы сохранить сохраненную часть [nggallery ...]
.
Я обновил ваше регулярное выражение в Интернете: https://www.regex101.com/r/rL8wP1/4
PS: В этом решении [nggallery ...]
не обязательно должно быть определенное атрибут, например href. Если вы хотите это сделать, вы можете использовать <a.*href\="(\[nggallery[^\]+]*\])".*?<\/a>
Ответ 3
Правда, вы не можете разобрать html с регулярными выражениями, как сделать поведение пуленепробиваемым с минималистическим лексер-парсером?
Это даст вам гораздо большую гибкость и контроль над вашим кодом.
<?php
$src = <<<EOF
<a href="[nggallery id=xx]"><span class="shutterset">
<img class="alignnone size-large wp-image-23067" title="Image Title"
src="http://example.com/wp-content/uploads/2015/06/image-title.jpg"
alt="" width="685" height="456" /></span></a>
<a href="[nggallery id=xxxxx]">Click here!</a>
<a title="title title" href="[nggallery id=xxx]" target="_blank">Title Link Title Link</a>
EOF;
// we "eat up" the source string by opening <a> tags, closing <a> tags or text
$tokens = array();
while ($src){
// check if $src begins with this pattern <a (any optional prop)[nggallery (any string)] (any optional prop)>
if (preg_match('/^<a [^>]*(\[nggallery [^\]]+\])[^>]*>/s', $src, $match)){
// here you can handle data with more flexibility
// you can grab the id or the [placeholder] via
//$match[1] = [nggallery id=xyz]
// we store the chunk of string and label it as an opening tag
$tokens[] = array('type' => 'OPENING_A', 'value' => $match[0]);
}else if (preg_match('/^<\/a>/s', $src, $match)){
// we store the chunk of string and label it as a closing tag
$tokens[] = array('type' => 'CLOSING_A', 'value' => $match[0]);
}else if (preg_match('/^./s', $src, $match)){
// we store the chunk of string, in this case a character and label it as text
$tokens[] = array('type' => 'TEXT', 'value' => $match[0]);
}
// finally we remove the identified pattern from the source string
// and continue "eating it up"
$src = substr($src, strlen($match[0]));
}
// once the source string has been consumed, we get this array
// var_dump($tokens);
// array (size=247)
// 0 =>
// array (size=2)
// 'type' => string 'OPENING_A' (length=9)
// 'value' => string '<a href="[nggallery id=xx]">' (length=28)
// 1 =>
// array (size=2)
// 'type' => string 'TEXT' (length=4)
// 'value' => string '<' (length=1)
// 2 =>
// array (size=2)
// 'type' => string 'TEXT' (length=4)
// 'value' => string 's' (length=1)
// 3 =>
// array (size=2)
// 'type' => string 'TEXT' (length=4)
// 'value' => string 'p' (length=1)
// ... ommited for brevity
// now with all the parsed data, we can rebuild the html
// as needed
$html = '';
// we keep a flag to now if we are inside a tag
// marked with ngggallery
$insideNGGalleryTag = false;
foreach ($tokens as $token){
if ($token['type'] == 'OPENING_A'){
$insideNGGalleryTag = true;
$html .= $token['value'];
}else if ($token['type'] == 'CLOSING_A'){
$insideNGGalleryTag = false;
$html .= $token['value'];
}else{
// if we are inside a nggallery tag, we will ignore
// all text inside it. here you could also remove
// html properties from the tag, move the [nggallery placeholder]
// inside the <a> or some other behavior you might need
if (!$insideNGGalleryTag){
$html .= $token['value'];
}
}
}
// finally echo or write to file the
// modified html, in this case it would return
var_dump($html);
// <a href="[nggallery id=xx]"></a>
// <a href="[nggallery id=xxxxx]"></a>
// <a title="title title" href="[nggallery id=xxx]" target="_blank"></a>
Ответ 4
/<a\b[^>]*href\s*=\s*"(\[nggallery id=[^"]+\])".*?<\/a>/i
Это поместит короткий код [nggallery id=XXX]
в группу 1, а затем заменит совпадение содержимым группы 1.
ПРИМЕЧАНИЕ: это предполагает достаточно хорошо отформатированный HTML, применяются обычные заявления об отказе.
Ответ 5
Немного поздно, но я думал, что брошу это в микс.
(Примечание - предупреждение!! это может быть трудно смотреть..)
изменено: для BBEdit.
Примечание. BBEdit использует механизм PCRE. Конструкции регулярных выражений BBEdit можно найти
здесь: https://gist.github.com/ccstone/5385334
Отформатирован:
# (?s)(<a(?=\s)(?>(?:(?<=\s)href\s*=\s*"\s*(\[nggallery\s+id\s*=\s*[^"\]>]*?\])"|".*?"|'.*?'|[^>]*?)+>)(?<!/>)(?(2)|(?!))).*?</a\s*>
(?s)
( # (1 start), Capture open a tag
<a # Open a tag
(?= \s )
(?> # Atomic
(?:
(?<= \s )
href \s* = \s* # href attribute
"
\s*
( # (2 start), Capture shortcode value
\[nggallery \s+
id \s* = \s* [^"\]>]*?
\]
) # (2 end)
"
| " .*? "
| ' .*? '
| [^>]*?
)+
>
)
(?<! /> ) # Not a self contained closure
(?(2) # Only a tags with href attr, shortcode value
| (?!)
)
) # (1 end)
.*? # Stuff inbetween
</a \s* > # Close a tag
Выход:
** Grp 0 - ( pos 0 , len 240 )
<a href="[nggallery id=xx]"><span class="shutterset">
<img class="alignnone size-large wp-image-23067" title="Image Title"
src="http://example.com/wp-content/uploads/2015/06/image-title.jpg"
alt="" width="685" height="456" /></span></a>
** Grp 1 - ( pos 0 , len 28 )
<a href="[nggallery id=xx]">
** Grp 2 - ( pos 9 , len 17 )
[nggallery id=xx]
----------------
** Grp 0 - ( pos 244 , len 46 )
<a href="[nggallery id=xxxxx]">Click here!</a>
** Grp 1 - ( pos 244 , len 31 )
<a href="[nggallery id=xxxxx]">
** Grp 2 - ( pos 253 , len 20 )
[nggallery id=xxxxx]
-----------------
** Grp 0 - ( pos 294 , len 90 )
<a title="title title" href="[nggallery id=xxx]" target="_blank">Title Link Title Link</a>
** Grp 1 - ( pos 294 , len 65 )
<a title="title title" href="[nggallery id=xxx]" target="_blank">
** Grp 2 - ( pos 323 , len 18 )
[nggallery id=xxx]
Ответ 6
Вот регулярное выражение, которое идеально соответствует вашим примерам.
(<a.*?href=")|([^\]]*?<\/a>)
Вместо того чтобы пытаться совместить все выражение сразу, я использовал оператор OR для указания двух отдельных регулярных выражений: один для начала тега a
, <a.*?href="
и один для конца тега [^\]]*?<\/a>
. Это может работать или не работать в одной операции замены, если нет, разбить на две операции замены, сначала запустить одно для регулярного выражения конечного тега, а затем запустить его для стартового тега. Сообщите мне, есть ли у вас дополнительные примеры, которые нарушают этот ответ.
Ответ 7
Я не знаю, почему вы хотите сделать это с помощью regex, когда это можно сделать с помощью манипуляций JavaScript DOM.
Я покажу вам основной способ, чтобы дать вам идею:
var div = document.createElement('div');
div.innerHTML = yourString;
var a = div.querySelector('a');
document.body.innerHTML = a.attributes[0].nodeValue;
Рабочая скрипта
Также проверьте documentFragment
Ответ 8
Поскольку вы не указали, я предполагаю, что нет вложенных тегов привязки, и вы просто хотите извлечь квадратный квадратный квадратный код, который находится там. Я также предполагаю, что идентификационный формат вашего кода "[nggallery".
Найдите с помощью этого
<\s*a(?=\s|>)[^>]*?(\[nggallery[^\]]+\])[^>]*>(.|\n)+?(<\s*\/\s*a\s*>)
ЗАМЕНИТЬ, используя
\1
(который должен быть первым записанным групповым обозначением для BBEdit)
Ответ 9
Как это?
(?<=nggallery\sid=xx]">).*(?=<\/a>)
Используйте глобальные и однострочные модификаторы (-g и -s). Это соответствует всем значениям между <a href="[nggallery id=xx]">
и </a>
. Я не уверен, правильно ли я понял вашу проблему или нет... но этот RegEx делает то, что я только что описал.