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
你可以使用这个正则表达式
<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>
<a.*(\[nggallery[^\]+]*\]).*?<\/a>当<a>一行中有多个标签时,Fab Sa的正则表达式会吞噬所有内容,因为.*开头不受限制,这将匹配不同的<a>标签.
通过限制允许的字符,您可以在某种程度上匹配您想要的:
<a\s[^>]*"(\[nggallery[^\]]*\])".*?<\/a>
^^^^^^^
Run Code Online (Sandbox Code Playgroud)
之后我强制要求至少一个空格,a以确保它不匹配其他一些标签,加上一些额外的限制.
无论如何,如果你发现它在一些极端情况下不起作用,你就是独立的.使用正则表达式操纵HTML通常是一个坏主意.
没错,你不能用正则表达式解析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)