php
  • regex
  • 2012-02-12 4 views 0 likes 
    0

    html形式のテキストを受け取ります。アンカータグのURLを私のドメインからのみに制限したいのですが、古いリンクを "xxx"(またはsmth 'else)に置き換えてください。
    入力:「<a href='otherdomain'>text</a>
    出力:「XXX」
    私は一種のここにこだわって、このかかわらを達成するために正規表現を使用しています:正規表現他のドメインへのリンクを削除する

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

    ここで何が悪いのでしょうか?

    +0

    あなたが浄化したい場合は、不在の属性引用やHTMLエンティティマスカレードを処理する必要があります。したがって、正規表現は一般的なケースだけを捕捉します。それは信頼できるフィルタとしては適していません。 (無駄な努力なしで)。 – mario

    +0

    [PHPでHTMLを解析し処理する方法]の可能な複製?(http://stackoverflow.com/questions/3577641/how-to-parse-and-process-html-with- PHPを – Gordon

    答えて

    2

    あなたは[^mydomain.*\"\']はリテラル 'M' を除く任意の文字に一致する」と言っているなど、 'Y'、 'D'、 'O'、...、 ''、 '*' を行うと

    のようなもの試してみてください:私は「A」と「のhref」の全体の言葉であり、正規表現が一致しないことを確認するa [^>]*\bhrefにごa.*hrefになっ

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

      ノート複数のタグにわたって。

    • あなたが/、それ以上
    • ノートに((?!mydomain)[^'"])+をエスケープする必要はありませんので、私が代わりに「/」の「#」に正規表現の区切り文字を変更しました。これは、「[ '^]一致 『を意味+それは』 mydomainをされていません。(?!負の先読みと呼ばれている。
    • \1。これは、URLの終了引用符マークが同じであることを確認しますオープニング引用符として、(括弧の最初のセットは['"]をキャプチャHWO参照?)。あなたが好ま場合は、おそらくそれなしで罰金になるだろう。PHPのために

    (更新バックスラッシュがする必要があるとき、私はいつも混同しているためPHPでエスケープする - 下記の@ GlitchMrのコメントを参照):

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

    アクションhereでご覧ください。あなたの目的に合わせて調整することができます。

    +0

    ありがとうございます。それは完全に動作します。 mydomainの前後で文字のマッチング方法を説明してください。 "sub.mydomain.com/page1"のように? – lvil

    +0

    投稿したインタラクティブな例へのリンクで、URLの1つを「sub.mydomain.com/page1」に変更しようとすると、それも一致していないことがわかります。または、 'mydomain.com'ではなく 'sub.mydomain.com/page1'と一致させたいですか? –

    +0

    それは大丈夫です、私はちょうどそれがどのように動作するか知りたかった。 – lvil

    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;  
        } 
    } 
    
    関連する問題