2013-06-19 10 views
7

Javaでは、href属性を持たない文字列に<a>タグを一致させる必要があります。たとえば、次の文字列で:一致するRegEx <a>特定の属性のないHTMLタグ

text <a class="aClass" href="#">link1</a> text <a class="aClass" target="_blank">link2</a> text 

(それはHREFを含んでいるため)それは<a class="aClass" href="#">link1</a>と一致しない必要がありますが(それはHREFが含まれていないため)それは<a class="aClass" target="_blank">link2</a>と一致する必要があります。

私は私のタグに一致するように正規表現を構築するために管理:(私はなどのHTMLパーサを使用することができます知っているが、私は必要

<a[^>]*>(.*?)</a> 

が、私はhrefの

でタグを解消する方法を見つけ出すことはできません正規表現でこれを行うには。

+5

? [HTMLは通常の言語ではありません](http:// stackoverflow。com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454)。 –

+3

正規表現でHTMLを解析する方が望ましい理由はさまざまです。エディタの中には、検索と置換のための正規表現の使用を許可するものがあります。同じエディタでは「ここにHTML解析コードを挿入する」がサポートされていません。あるいは、非常にひどくフォーマットされたhtmlコードからデータを取り出すと、解析エラーが発生する可能性があります。または宿題の割り当ては正規表現を使用し、解析エンジンは使用しないと言いました。 htmlの代わりにhtmlのサンプルが含まれていたとしたら... htmlをエンジンで解析することは、必ずしも最良の解決策であるとは限りません。 –

+1

"html"と "regex"の両方の単語に質問があるたびに、自動的にそのリンクを投稿するボットのようなスクリプトを実行していることは間違いないと思います* "[X] HTMLを解析できません正規表現で... "*答え。陽気。 – acdcjunior

答えて

18

説明

は、これらのような<a[^>]*のようなregexsには注意してください<abbr>または<address>のようなaで始まる他の有効なhtmlタグと一致します。また、単に文字列hrefの存在を探して、その文字列がこの式の別の属性の値内かな<a hreflang="en"...

よう<a class="thishrefstuff"...、または別の属性の一部としての可能性としては十分だろうではありません。

  • すべてのアンカータグと一致<a ... 属性を含まない</a>
  • これは、タグ名がaではなく、単にa
  • <address>なども有効な hreflang='en'のような属性の名前に埋め込まれた部分文字列 hrefを持っているか、構成された属性を無視文字で始まるタグで強制されます Attributehref="some value"
  • が拡大bogus='href=""'

<a(?=\s|>)(?!(?:[^>=]|=(['"])(?:(?!\1).)*\1)*?\shref=['"])[^>]*>.*?<\/a>

enter image description here

  • <a(?=\s|>)一致オープンタグのようなすべての適切にフォーマットされた属性の値部分内のすべての文字を無視した後、次を確保しますタグ名は空白か閉じ括弧のいずれかです。 sがaと他のないものにするために名前を強制的に
  • 私たちは、このタグのhrefを見つけた場合先にこれを否定表情を開始し、その後、タグのこのタイプは、我々が
    • (?:を探しているタグではありません(?!タグを残してから正規表現エンジンを防止する全ての非タグ閉鎖文字一致[^>=]
    • タグ内のすべての文字を移動するために、非キャプチャグループを開始し、すべての文字を
    • |に一致盲目的続行エンジンを防止する非等号または
    • =(['"])は、等号の後に開いた二重引用符または一重引用符を続けます。引用は、それが正しく後で
    • (?:(?!\1).)*試合オープン引用
    • \1が正しい近くの引用
    • )*?が非キャプチャを閉じ一致一致する近くの引用符ではないすべての文字を組み合わせることができ、グループ2に取り込まれますグループおよびリピートは、所望のhref属性に一致するまで
    • \shref=['"]まで必要なだけ頻繁に繰り返されます。

      入力:\s=["']は、属性名は、単に

    • )は否定先読み
  • [^>]*>.*?<\/a>試合に

Javaのコード例を閉鎖するためのオープンから文字列全体を閉じてhrefが保証されますテキスト

<abbr>RADIO</abbr> text <a class="aClass" href="#">link1</a> text <a bogus='href=""' class="aClass" target="_blank">link2</a> text

コード

あなたは非HREFアンカータグを削除するために置き換える機能でこれを使用するために探しているなら、ただ何もすべての一致を置き換えます。

import java.util.regex.Pattern; 
import java.util.regex.Matcher; 
class Module1{ 
    public static void main(String[] asd){ 
    String sourcestring = "source string to match with pattern"; 
    Pattern re = Pattern.compile("<a(?=\\s|>)(?!(?:[^>=]|=(['\"])(?:(?!\\1).)*\\1)*?\\shref=['\"])[^>]*>.*?<\\/a> 
",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 
    Matcher m = re.matcher(sourcestring); 
    int mIdx = 0; 
    while (m.find()){ 
     for(int groupIdx = 0; groupIdx < m.groupCount()+1; groupIdx++){ 
     System.out.println("[" + mIdx + "][" + groupIdx + "] = " + m.group(groupIdx)); 
     } 
     mIdx++; 
    } 
    } 
} 

マッチあなたは正規表現を使用する必要がないのはなぜ

$matches Array: 
(
    [0] => Array 
     (
      [0] => <a bogus='href=""' class="aClass" target="_blank">link2</a> 
     ) 

    [1] => Array 
     (
      [0] => 
     ) 

) 

+0

完璧な答え。それは私がやろうとしていることとうまくいっています。唯一の問題は、引用符を含まないhref属性がある場合には、それが一致するということです。例: '' – user2287359

4

を私はあなたが必要は、正規表現でそれを行うためにだろうが、あなたは否定先読みを使用することができ、それは奇妙なことがわかります。

<a(?![^>]+href).*?>(.*?)</a> 
+0

複数の行にまたがるタグに一致するでしょうか? – Raedwald

+0

@Raedwald DOTALLとすることができます –

-1

1つのオプションは、最初にすべてのタグと一致させてから、それらを無視できるように正規表現を使用することです。だからあなたの擬似コードは次のようになります。

<a>tags = html.find(all<a>tags); 
for(String <a>tag : <a>tags){ 
    if(<a>tag.isHref()) continue; 
    //do proccessing 
} 
+0

-1 OPはこれをhge解析エンジンではなくregexで行う方法を指定しました。 –

+0

@Denomalesその擬似コードは... html解析エンジンではありません。私はリンクを張ったり、パーサをどこにでも置いてはいけません。私はちょうど正規表現の代わりの使い方を示唆しています。 –

0

私は、Javaの専門家ではないですが、あなたはこのような何かを試すことができます。

String regex = new String("(?i)<a(?>[^h>]++|(?<!)h++|h++(?!ref\\s*+=))*>((?>[^<]++|<(?!/a>))*)</a>"); 
String replacement = new String("$1"); 
str.replaceAll(regex,replacement); 
関連する問題