2012-09-21 78 views
0

的匹配我很抱歉,因爲我對正則表達式知之甚少,我甚至不明白這個正則表達式在做什麼(我沒有寫它 - source),除了它搜索可以突出顯示的某個術語。正則表達式忽略<script>標籤

這裏是正則表達式:

/(\b$term|$term\b)(?!([^<]+)?>)/iu 

的問題是我需要確保它不會<script></script>標籤之間的匹配任何內容。現在我知道可以編寫腳本標記的方式有很多種,但我真正需要的是忽略<script/script>之間的任何文本,其中考慮到script<之間的可能空格,如< script/script >

有人能夠以這種方式修改它嗎?我會通知插件的作者誰寫這個reg-ex包括在未來的版本。

編輯:下面是其來源的功能:

function relevanssi_highlight_terms($excerpt, $query) { 
    $type = get_option("relevanssi_highlight"); 
    if ("none" == $type) { 
     return $excerpt; 
    } 

    switch ($type) { 
     case "mark":      // thanks to Jeff Byrnes 
      $start_emp = "<mark>"; 
      $end_emp = "</mark>"; 
      break; 
     case "strong": 
      $start_emp = "<strong>"; 
      $end_emp = "</strong>"; 
      break; 
     case "em": 
      $start_emp = "<em>"; 
      $end_emp = "</em>"; 
      break; 
     case "col": 
      $col = get_option("relevanssi_txt_col"); 
      if (!$col) $col = "#ff0000"; 
      $start_emp = "<span style='color: $col'>"; 
      $end_emp = "</span>"; 
      break; 
     case "bgcol": 
      $col = get_option("relevanssi_bg_col"); 
      if (!$col) $col = "#ff0000"; 
      $start_emp = "<span style='background-color: $col'>"; 
      $end_emp = "</span>"; 
      break; 
     case "css": 
      $css = get_option("relevanssi_css"); 
      if (!$css) $css = "color: #ff0000"; 
      $start_emp = "<span style='$css'>"; 
      $end_emp = "</span>"; 
      break; 
     case "class": 
      $css = get_option("relevanssi_class"); 
      if (!$css) $css = "relevanssi-query-term"; 
      $start_emp = "<span class='$css'>"; 
      $end_emp = "</span>"; 
      break; 
     default: 
      return $excerpt; 
    } 

    $start_emp_token = "*[/"; 
    $end_emp_token = "\]*"; 

    if (function_exists('mb_internal_encoding')) 
     mb_internal_encoding("UTF-8"); 

    $terms = array_keys(relevanssi_tokenize($query, $remove_stopwords = true)); 

    $phrases = relevanssi_extract_phrases(stripslashes($query)); 

    $non_phrase_terms = array(); 
    foreach ($phrases as $phrase) { 
     $phrase_terms = array_keys(relevanssi_tokenize($phrase, false)); 
     foreach ($terms as $term) { 
      if (!in_array($term, $phrase_terms)) { 
       $non_phrase_terms[] = $term; 
      } 
     } 
     $terms = $non_phrase_terms; 
     $terms[] = $phrase; 
    } 

    usort($terms, 'relevanssi_strlen_sort'); 

    get_option('relevanssi_word_boundaries', 'on') == 'on' ? $word_boundaries = true : $word_boundaries = false; 
    foreach ($terms as $term) { 
     $pr_term = preg_quote($term, '/'); 
     if ($word_boundaries) { 
      $excerpt = preg_replace("/(\b$pr_term|$pr_term\b)(?!([^<]+)?>)/iu", $start_emp_token . '\\1' . $end_emp_token, $excerpt); 
     } 
     else { 
      $excerpt = preg_replace("/($pr_term)(?!([^<]+)?>)/iu", $start_emp_token . '\\1' . $end_emp_token, $excerpt); 
     } 
     // thanks to http://pureform.wordpress.com/2008/01/04/matching-a-word-characters-outside-of-html-tags/ 
    } 

    $excerpt = relevanssi_remove_nested_highlights($excerpt, $start_emp_token, $end_emp_token); 

    $excerpt = str_replace($start_emp_token, $start_emp, $excerpt); 
    $excerpt = str_replace($end_emp_token, $end_emp, $excerpt); 
    $excerpt = str_replace($end_emp . $start_emp, "", $excerpt); 
    if (function_exists('mb_ereg_replace')) { 
     $pattern = $end_emp . '\s*' . $start_emp; 
     $excerpt = mb_ereg_replace($pattern, " ", $excerpt); 
    } 

    return $excerpt; 
} 
+1

不要用HTML混合正則表達式! – hsz

+1

人們會因爲使用reg ex爲HTML而生氣,它不好使 –

+0

@hsz這不是我的插件。它已經使用這個正則表達式,我試圖糾正它創建的一些錯誤匹配。 –

回答

1

由於lookbehind assertions需要固定的長度,你不能用它來尋找一個前<script>標籤某處搜索長期之前。

所以,更換所需的所有情況後,你需要第二次到恢復,似乎是一個<script>標籤內的修飾的術語的那些事件。

# provide some sample data 
$excerpt = 'My name is bob! 

And bob is cool. 

<script type="text/javascript"> 
var bobby = "It works fine even if you already have tagged the term <em>bob</em> inside the script tag."; 
alert(bobby); 

var bob = 5; 
</script> 

Yeah, the word "bob" works fine.'; 

$start_emp_token = '<em>'; 
$end_emp_token = '</em>'; 
$pr_term = 'bob'; 

# replace everything (not in a tag) 
$excerpt = preg_replace("/(\b$pr_term|$pr_term\b)(?!([^<]+)?>)/iu", $start_emp_token . '$1' . $end_emp_token, $excerpt); 

# undo some of the replacements 
$excerpt = preg_replace_callback('#(<script(?:[^>]*)>)(.*?)(</script>)#is', 
         create_function(
         '$matches', 
         'global $start_emp_token, $end_emp_token, $pr_term; 
          return $matches[1].str_replace("$start_emp_token$pr_term$end_emp_token", "$pr_term", $matches[2]).$matches[3];' 
         ), 
         $excerpt); 

var_dump($excerpt); 

上面的代碼產生以下輸出:

string(271) "My name is <em>bob</em>! 

And <em>bob</em> is cool. 

<script type="text/javascript"> 
var bobby = "It works fine even if you already have tagged the term <em>bob</em> inside the script tag."; 
alert(bobby); 

var bob = 5; 
</script> 

Yeah, the word "<em>bob</em>" works fine." 
+0

謝謝,但它似乎沒有做任何事情。 –

+0

您的正則表達式正在成功匹配'script'標籤,但它並未刪除令牌。 –

+0

對我來說,它工作得很好。我剛剛通過添加一些示例數據編輯了我的回覆。你可以嘗試一下,看看它是否也適用於你? –

2

最準確的方法是:

  • 解析HTML以適當的HTML解析器
  • 忽略字符串在<script>標籤內。

您不想嘗試使用正則表達式解析HTML。下面是對原因的解釋:http://htmlparsing.com/regexes.html

從長遠來看,它會讓你難過。請參閱http://htmlparsing.com/的其餘部分,瞭解一些可以幫助您入門的提示。

+0

這是不可能的我的問題的上下文。這是一個已經構建的wordpress CMS插件的一部分。我不重寫插件,我試圖修改它的一小部分行爲。正則表達式只是尋找頁面中的某個單詞來突出顯示,它已經忽略了html,但不會忽略'