如何忽略由特定字符串包装的正则表达式匹配


How to ignore regex matches wrapped by a particular string?

我对一个项目的一些功能有一个很好的想法,我已经尽力实现它,但我需要一点帮助来实现预期的效果。所讨论的页面是:http://dev.favorcollective.com/guidelines/(只是提供一些上下文)

我使用php的preg_replace来浏览特定页面的内容(巨大的字符串),我让它搜索术语表术语,然后我用一些html来包装术语表定义工具提示。

下面是我当前的代码:

function annotate($content)
{
    global $glossary_terms;
    $search =  array();
    $replace = array();
    $count=1;
    foreach ($glossary_terms as $term):
        array_push($search,'/'b('.preg_quote($term['term'],'/').')[?=a-zA-Z]*/i');
        $id = "annotation-".$count;
        $replacement = '<a href="'.get_bloginfo('url').'/glossary#'.preg_replace( '/'s+/', '', $term['term']).'" class="annotation" rel="'.$id.'">'.$term['term'].'</a><span id="'.$id.'" style="display:none;"><span class="term">'.$term['term'].'</span><span class="definition">'.$term['def'].'</span></span>';
         array_push($replace,(string)$replacement);
         $count++;
    endforeach;
    return preg_replace($search, $replace, $content);
}

•但是如果我想忽略<h#>& lt;/h #比;标签?

•我也有一个特定的字符串,我不希望在其中匹配特定的术语。例如,我希望单词"熟练程度"匹配任何时候它不使用在"ACTFL熟练度指南"的上下文中,我该如何去添加异常到我的正则表达式?这有可能吗?

•最后,如何将匹配的文本作为变量返回?目前,当我匹配以"s"或"ing"结尾的术语时(故意),我的脚本打印匹配的术语,而不是匹配的原始字符串(即它用"描述"替换"描述")。有什么办法吗?

不是一个PHP的家伙(c#),但这里开始。我假设:

'/'b('.preg_quote($term['term'],'/').')[?=a-zA-Z]*/i'将映射到这个更可读的模式:

/'b(ESCAPED_TERM)[?=a-zA-Z]*/i

so,只要排除<h#>只有当您可以假设您的数据是简单的非嵌套的大小写:<h#>TERM<h#>时,regex才可以。如果可以,可以使用负向前看断言:

/'b(ESCAPED_TERM)(?!<h'd>)[?=a-zA-Z]*/i

你可以使用前向和后向来处理你的特殊情况:

/'b(ESCAPED_TERM|(?<!ACTFL )Proficiency(?!'sGuidelines))(?!<h'd>)[?=a-zA-Z]*/i

注意:如果你有一堆这样的特殊情况,PHP可能(应该)有一个"忽略空白"标志,它会让你把每个标记放在换行符上。

正则表达式是令人敬畏的,美妙的,神奇的。但凡事都有极限。

这就是为什么使用PHP这样的语言来提供额外的功能是很好的。:)

你可以用非贪婪的正则表达式去掉头吗?

$content = preg_replace('/<h[1-6]>.*?<'/h[1-6]>/sim', "", $content);

如果非贪婪的计算不起作用,那么假设你的头文件中没有任何其他HTML呢?

$content = preg_replace('/<h[1-6]>[^<]*<'/h[1-6]>/im', "", $content);

同样,您可能希望使用sprintf来简化您的替换:

/*
  1  get_bloginfo('url')
  2  preg_replace( '/'s+/', '', $term['term']).
  3  $id
  4  $term['term']
  5  $term['def']
*/
$rfmt = '<a href="%1$s/glossary#%2$s" class="annotation" rel="%3$s">%4$s</a><span id="%3$s" style="display:none;"><span class="term">%4$s</span><span class="definition">%5$s</span></span>';
...
$replacement = sprintf($rfmt, get_bloginfo('url'), preg_replace( '/'s+/', '', $term['term']), $id, $term['term'], $term['def'] );