2012-02-12 123 views
0

我收到格式爲html的文本。我想限制錨標記的網址只能從我的網域中用「xxx」(或其他)替換舊鏈接。
輸入:「<a href='otherdomain'>text</a>
輸出:「XXX」
我使用正則表達式來實現這一點,雖然我那種堅持在這裏:正則表達式刪除指向另一個域的鏈接

$pattern ='/<a.*href=[\'|\"]http.?:\/\/[^mydomain.*\"\']*[\'|\"].*<\/a>/i'; 
$replace ='xxx'; 
echo preg_replace($pattern, $replace, $string); 

這裏有什麼問題?

+0

如果是用戶輸入你想清理,那麼你也將不得不處理缺少的屬性引號或HTML實體僞裝。正則表達式因此只會捕獲常見的情況;它不適合作爲可靠的過濾器。 (沒有過多的努力) – mario 2012-02-12 12:11:43

+0

[如何解析和處理HTML與PHP?]可能的重複(http://stackoverflow.com/questions/3577641/how-to-parse-and-process-html-with- php) – Gordon 2012-02-12 12:12:50

+0

@ Gordon:我認爲解析它並不容易,因爲我收到標記作爲已通過篩選的字符串的一部分 – lvil 2012-02-12 12:18:57

回答

2

當你做[^mydomain.*\"\']你說的「匹配任何字符,除了字符 'M', 'Y', 'd', 'O',..., '', '*' 等

試着這麼做:

#<a [^>]*\bhref=(['"])http.?://((?!mydomain)[^'"])+\1 *>.*?</a>#i 

注:

  • 我把你的a.*hrefa [^>]*\bhref,以確保在「A」和「href」的整個單詞和正則表達式不匹配通過多個標籤
  • 我改變了正則表達式分隔符爲「#」,而不是「/」,這樣你就不必逃避/更多
  • 注意((?!mydomain)[^'"])+。這意味着「匹配[^'‘] +未MYDOMAIN’的(?!被稱爲負前瞻
  • 注意\1。這將確保該URL的右引號是一樣的作爲開幕引號(見藿第一組括號捕獲['"]?)。你可能會沒有它的罰款,如果你優先。

對於PHP(更新,因爲我總是把這當反斜槓需要在PHP中可以逃脫 - 請參閱下面的@ GlitchMr的評論):

$pattern = '#<a [^>]*\bhref=([\'"])http.?://((?!mydomain)[^\'"])+\1 *>.*?</a>#i'; 

看到它在行動here,在那裏你可以調整它到你的目的。

+0

謝謝。它完美的作品。你能解釋一下如何在mydomain之前和之後實現字符匹配嗎?像「sub.mydomain.com/page1」? – lvil 2012-02-12 12:38:34

+0

如果您嘗試將其中一個URL更改爲我發佈的交互式示例的鏈接中的「sub.mydomain.com/page1」,則會看到該內容也不匹配。或者你想*匹配「sub.mydomain.com/page1」而不是「mydomain.com」? – 2012-02-12 12:40:44

+0

這是正常的,我只是想知道它是如何工作的。 – lvil 2012-02-12 12:44:36

1

(雖然這是沒有理由不解釋一下。)

如果你想匹配「任何不是」那你平時要用的斷言;在你的情況下,negative lookahead assertion

(?!mydomain\.com).*? 

這將匹配任何.*?,但不允許值其之前。

還注意到的是:

  • 應該[\"\']而不是[\'|\"]。替代符號在字符類中沒有意義。
  • .*通常應該是.*?不太匹配太寬泛。
  • [^>]*是在標籤內匹配的常見習慣用語。
  • 您可以使用其他分隔符#<a...*>#i代替/以避免轉義。
0

[]是字符集合運算符。你的模式將是一個很大更多的理解爲

$pattern ='!<a\s.*?\shref\s*=\s*([\'"])https?:://mydomain.*?\1.*?</a>!is'; 

注:

  • 我空格分隔令牌
  • 交換正則表達式引用字符,避免\/
  • 使用一個反向引用以匹配報價。
2

下面是我正在使用的代碼的一部分。它使用用戶函數來更改正則表達式挖掘出的文本。祝你好運:)

class RedirectLinks { 
    /** 
    * Callback used by convert_external_links_to_internal on each url found 
    * 
    * @param array $matches 
    * @return string 
    */ 
    public static function urlMatchCallback($matches) 
    { 
     if (stripos($matches[1], 'http://') === false || 
      stripos($matches[1], 'example.com') !== false 
      ) { 
      return $matches[0]; // do not modify 
     } 
     // encrypt url for redirection   
     $sURL = $matches[1]; 
     return "href=\"#\" onclick=\"showmessage('$sURL');\""; 
    } 

    /** 
    * Converts external links in text to internal ones 
    * 
    * @param string $str - text 
    * @return the processed text 
    */ 
    public static function convertExternalLinksToInternal($str) { 
     // convert external links to internal redirections 
     $str = preg_replace_callback("/href=\"([^\"]*)\"/is", 'RedirectLinks::urlMatchCallback', $str); 

     return $str;  
    } 
} 
相關問題