2016-08-02 9 views
1

Ich habe versucht, eine Regex für meine Anforderung zu finden, aber ich konnte keine finden. Wenn jemand auf dieses stieß, bitte helfen Sie mir.Schließen Sie ein Muster aus, wenn es sich in einem anderen Muster befindet

Zum Beispiel, wenn HTML-Kommentar in einem JSP-Kommentar ist, dann nicht berühren, sonst machen Sie es als JSP-Kommentar.

Condition: 1 
<!-- normal HTML comment --> 

with 

<%-- normal HTML comment --%> 

Aber passen Sie die HTML-Kommentare in den JSP-Kommentaren nicht wie unten an.

Codition: 2 
<%-- normal JSP comment 

    <!-- inside html comment here --> 
     other comment stuff 
<!-- another inside html comment here --> 

--%> 

eine Java-Lösung wird sehr geschätzt.

+1

"Ich habe versucht, einen regulären Ausdruck für meine Anforderung zu finden, aber ich konnte nicht finden." - Das ist ein Beispiel für [warum reguläre Ausdrücke nicht gut für nicht-reguläre Problemdomänen wie HTML passen] (http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self) -contained-tags/1732454 # 1732454) usw. Sie könnten einen Ausdruck erstellen, der die Bedingungen 1 und 2 behandelt (und es könnte sehr komplex werden) und dann die Bedingung 3 usw. auftreten. Verwenden Sie besser einen Parser, der die Problemdomäne versteht (JSP-Code in Ihrem Fall). – Thomas

+0

Sie werden mehr als das brauchen, wenn dies eine Mischung aus HTML und JSP ist. Ist es eine Mischung? – sln

+0

@sln ja ist es. – kakurala

Antwort

1

Beim Versuch, etwas zu finden, das nicht im Kontext "X" oder Kontext "Y" ist, verwende ich immer die Formel von The Greatest Regex Trick Ever. Der Trick besteht darin, eine Capture-Gruppe auf der rechten Seite einer Alternation zu erstellen, die das hat, was Sie wollen, und alle anderen Kontexte, die Sie nicht wollen, auf der linken Seite der Alternation.

Darüber hinaus muss die Regex Zeichenfolgenliterale ignorieren. Ihre Regex würde wie folgt aussehen:

".*?(?<!\\)"|(?s)<%--.*?--%>|<!--(.*?)--> 

Und dann würde der Code nur die Zeichenfolge ersetzen, wenn es eine erste Erfassungsgruppe gibt.

String input = getJSPString(); 

final Pattern p = Pattern.compile(
    "\".*?(?<!\\\\)\"|" + // ignore string literals 
    "(?s)<%--.*?--%>|" + // ignore JSP comments 
    "<!--(.*?)-->");  // capture HTML comments in group #1 
Matcher m = p.matcher(input); 
StringBuffer sb = new StringBuffer(); 
while (m.find()) { 
    if (m.group(1) != null) { 
     m.appendReplacement(sb, "<%--$1--%>"); 
    } 
} 
m.appendTail(sb); 
String output = sb.toString(); 

Ideone Demo

+0

Angenommen, wir haben solche Muster, dann wäre die Kombination von Bedingungen/Ausdrücken kompliziert eine beliebige Verknüpfung dafür? – JavaHopper

+1

@JavaHopper Um mehrere Kontexte zu ignorieren, behalten Sie einfach ad Weiter nach links. So 'notThis | orThis | evenThis | (WeWantThis)' – 4castle

+0

Danke für den Trick @ 4castle, aber hier funktioniert es nicht. Stattdessen stimmt es mit allen HTML-Kommentaren überein, unabhängig davon, wo es sich befindet. – kakurala

0

Sie erwähnen Ihre Quelle ein HTML-Mix ist, werde ich diese Variante bietet
die Einführung können Komplikationen HTML-Tags entfernt.

Mit der Zugabe der Atomgruppe und der \G Anker
gibt es wenig Risiko von Stack-Überlauf.

Ersetzen mit

Raw Regex:

\G((?><(?:script(?:\s+(?:"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])*?)+)?\s*>[\S\s]*?</script\s*|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:(?:(?:"[\S\s]*?")|(?:'[\S\s]*?'))|(?:[^>]*?))+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?)))|%--[\S\s]*?--%)>|(?!<!--[\S\s]*?-->)[\S\s])*)<!--([\S\s]*?)--> 

Streich Regex:

"\\G((?><(?:script(?:\\s+(?:\"[\\S\\s]*?\"|'[\\S\\s]*?'|(?:(?!/>)[^>])*?)+)?\\s*>[\\S\\s]*?</script\\s*|(?:/?[\\w:]+\\s*/?)|(?:[\\w:]+\\s+(?:(?:(?:\"[\\S\\s]*?\")|(?:'[\\S\\s]*?'))|(?:[^>]*?))+\\s*/?)|\\?[\\S\\s]*?\\?|(?:!(?:(?:DOCTYPE[\\S\\s]*?)|(?:\\[CDATA\\[[\\S\\s]*?\\]\\])|(?:ATTLIST[\\S\\s]*?)|(?:ENTITY[\\S\\s]*?)|(?:ELEMENT[\\S\\s]*?)))|%--[\\S\\s]*?--%)>|(?!<!--[\\S\\s]*?-->)[\\S\\s])*)<!--([\\S\\s]*?)-->" 

Expanded/Formatiert:

\G       # G anchor 
(       # (1 start) 
     (?>       # Atomic group start 

      <        # Begin a Tag <, but not an html comment 
      (?: 
       script      # Script 
       (?: 
        \s+ 
        (?: 
          " [\S\s]*? " 
         | ' [\S\s]*? ' 
         | (?: 
           (?! />) 
           [^>] 
         )*? 
        )+ 
       )? 
       \s* > 
       [\S\s]*? </script \s* 
      |        # or, 
       (?:       # Non-attribute 
        /? 
        [\w:]+ 
        \s* 
        /? 
       ) 
      |        # or, 
       (?:       # Attribute 
        [\w:]+ 
        \s+ 
        (?: 
          (?: 
           (?: " [\S\s]*? ") 
          | (?: ' [\S\s]*? ') 
         ) 
         | (?: [^>]*?) 
        )+ 
        \s* 
        /? 
       ) 
      |        # or, 
       \?       # <? ?> form 
       [\S\s]*? 
       \? 
      |        # or, 
       (?:       # Misc <! > forms 
        ! 
        (?: 
          (?: 
           DOCTYPE 
           [\S\s]*? 
         ) 
         | (?: 
           \[CDATA\[ 
           [\S\s]*? 
           \]\] 
         ) 
         | (?: 
           ATTLIST 
           [\S\s]*? 
         ) 
         | (?: 
           ENTITY 
           [\S\s]*? 
         ) 
         | (?: 
           ELEMENT 
           [\S\s]*? 
         ) 
        ) 
       ) 
      |        # or, 
       %-- [\S\s]*? --%    # JSP comment 
      ) 
      >        # End a Tag > 

     |        # or, 
             # A character that does 
             # not begin a html comment 
      (?! <!-- [\S\s]*? -->) 
      [\S\s] 
    )*       # Atomic group end, 0 to many times 
)        # (1 end) 

<!-- 
([\S\s]*?)     # (2), Finally, the Html comment 
--> 
+0

Was würde den Stapel überlaufen lassen? Ich sehe keine Rekursion. – 4castle

+0

@ 4castle - Ich kenne die Fakten nicht zu viel anders als Java-Regex-Implementierung ist von rekursiver Natur. Ich denke, das beinhaltet Backtracking. Google es, es ist überall. – sln

+0

@sln, danke für deine Bemühungen. Ich habe versucht 4castle's Code-Version mit kleinen Änderungen und es funktioniert für meine Anforderung. – kakurala

0

könnten Sie diese patte verwenden rn

(<!(--(?:[^-]|-(?!->))*?--)>)(?!((?!<%--)[\s\S])*?--%>) 

und ersetzen w/<%$2%>
Demo

Verwandte Themen