【问题标题】:How to ignore regex matches wrapped by a particular string?如何忽略由特定字符串包裹的正则表达式匹配?
【发布时间】:2019-09-23 00:23:24
【问题描述】:

我对项目中的某些功能有一个很棒的想法,我已经尽力实现它,但我需要一些帮助才能达到预期的效果。有问题的页面是: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);
}

• 但是,如果我想忽略 #> 标记内的匹配项怎么办?

• 我还有一个特定的字符串,我不想在其中匹配特定的术语。例如,我希望“熟练度”这个词在“ACTFL 熟练度指南”的上下文中不使用的任何时候都匹配,我将如何为我的正则表达式添加例外?这甚至是一种选择吗?

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

【问题讨论】:

  • 欢迎来到 SO!请阅读this introductory article 使用正则表达式处理 HTML。
  • 您或其他人能否提供一个示例,说明我尝试使用 PHP HTML 解析器实现的目标?我应该修改我的问题吗?我从来没有新的正则表达式如此有限——我的印象是编程的一切都结束了。圣杯。
  • 编程没有圣杯。我认为您不应该以完全改变范围的方式修改这个问题,因为已经有一个相当不错的答案。提出一个新问题来询问解析器示例。

标签: php regex


【解决方案1】:

不是 php 人 (c#),但这里有。我假设:

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

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

所以,就排除 类型标签而言,只有当您可以假设您的数据是简单的 非嵌套 情况时,正则表达式才可以:TERM。如果可以,您可以使用否定的前瞻断言:

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

您可以使用lookahead with a lookbehind 来处理您的特殊情况:

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

注意:如果您有很多这些特殊情况,PHP 可能(应该)有一个“忽略空格”标志,它可以让您将每个标记放在换行符上。

【讨论】:

    【解决方案2】:

    正则表达式很棒,很棒,很神奇。但凡事都有其局限性。

    这就是为什么使用像 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'] );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-10-29
      • 1970-01-01
      • 2021-01-31
      • 2014-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多