RegEx删除<a和</a>标记之间的所有标记,但[和]内除外

mar*_*dge 16 html regex html-parsing

试图找出正则表达式给我一个大脑抽筋:)

我正在href使用允许我在内容上运行正则表达式的插件,用WordPress帖子内容中的单个短代码替换数千个单独的链接.

我不是尝试将SQL查询与RegEx结合起来,而是分两个阶段进行:首先是SQL查找/替换每个单独的URL到单个短代码,第二个阶段,删除其余的'href`链接标记.

这些是我从第一步开始就拥有的一些例子; 如您所见,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>
Run Code Online (Sandbox Code Playgroud)

现在,我需要删除前导和结尾之间的所有href链接标记 - span,img等等,只留下短代码.<a</a>[nggallery id=xxx]

我从这里开始:https://www.regex101.com/r/rL8wP1/2

但我不知道如何防止[nggallery id=xxx]在RegEx中捕获短代码.

2015年7月9日更新

@ nhahtdh的答案看起来工作得很完美,不是太贪心,也不会吃邻近的html链接.使用()作为分隔符,并$1替换为WordPress中的正则表达式插件.(如果使用BBEdit,则需要使用\1)

( <a\s[^>]*"(\[nggallery[^\]]*\])".*?<\/a> )
Run Code Online (Sandbox Code Playgroud)

2015年7月2日更新

感谢Fab Sa (下面的回答),他的正则表达式在https://www.regex101.com/r/rL8wP1/4

<a.*(\[nggallery[^\]+]*\]).*?<\/a>
Run Code Online (Sandbox Code Playgroud)

在regex101模拟器中工作,但是当在BBEdit文本编辑器或运行正则表达式的WordPress插件中使用时,他的正则表达式会删除[nggallery id=***]短代码.太贪心了吗?还有其他问题吗?

2015年7月1日更新:

我知道,我知道,re:RegEx匹配开放标签,除了XHTML自包含标签你不能用HTMLEX PARSE HTML

Fab*_* Sa 7

你可以使用这个正则表达式

<a.*(\[nggallery[^\]+]*\]).*?<\/a>
Run Code Online (Sandbox Code Playgroud)

全球(旗帜g).此正则表达式将匹配链接并保存该[nggallery ...]部分.您可以使用$ 1替换所有匹配以保留已保存的[nggallery ...]部分.

我已在线更新你的正则表达式:https://www.regex101.com/r/rL8wP1/4

PS:在这个解决方案中[nggallery ...],不需要像href这样的特定属性.如果你想强迫它,你可以使用<a.*href\="(\[nggallery[^\]+]*\])".*?<\/a>


nha*_*tdh 7

<a.*(\[nggallery[^\]+]*\]).*?<\/a><a>一行中有多个标签时,Fab Sa的正则表达式会吞噬所有内容,因为.*开头不受限制,这将匹配不同的<a>标签.

通过限制允许的字符,您可以在某种程度上匹配您想要的:

<a\s[^>]*"(\[nggallery[^\]]*\])".*?<\/a>
  ^^^^^^^
Run Code Online (Sandbox Code Playgroud)

之后我强制要求至少一个空格,a以确保它不匹配其他一些标签,加上一些额外的限制.

无论如何,如果你发现它在一些极端情况下不起作用,你就是独立的.使用正则表达式操纵HTML通常是一个坏主意.


Jua*_*ank 5

没错,你不能用正则表达式解析html,如何用简约的lexer-parser使这个行为变得无懈可击?它将为您提供更多的灵活性和对代码的控制.

<?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>
Run Code Online (Sandbox Code Playgroud)