2009-02-03 2 views
0

par exemple:
Texte:condition d'utilisation des expressions régulières

<!-- Nav bar -->

<TD>

<A HREF="/home"><IMG SRC="/images/home.gif"></A>

<IMG SRC="/images/spacer.gif">

<A HREF="/search"><IMG SRC="/images/search.gif"></A>

<IMG SRC="/images/spacer.gif">

<A HREF="/help"><IMG SRC="/images/help.gif"></A>

</TD>

Regex:

(<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>(?(1)\s*</[Aa]>) 

Résultat:

<A HREF="/home"><IMG SRC="/images/home.gif"></A>

<IMG SRC="/images/spacer.gif">

<A HREF="/search"><IMG SRC="/images/search.gif"></A>

<IMG SRC="/images/spacer.gif">

<A HREF="/help"><IMG SRC="/images/help.gif"></A>


quel est le "? (1)" signifie? Lorsque je l'exécute en Java, il provoque une exception: java.util.regex.PatternSyntaxException, le "? (1)" ne peut pas être reconnu.

L'explication dans le livre est:

This pattern requires explanation. (<[Aa]\s+[^>]+>\s*)? matches an opening <A> or <a> tag (with any attributes that may be present), if present (the closing ? makes the expression optional). <[Ii][Mm][Gg]\s+[^>]+> then matches the <IMG> tag (regardless of case) with any of its attributes. (?(1)\s*</[Aa]>) starts off with a condition: ?(1) means execute only what comes next if backreference 1 (the opening <A> tag) exists (or in other words, execute only what comes next if the first <A> match was successful). If (1) exists, then \s*</[Aa]> matches any trailing whitespace followed by the closing </A> tag.

+0

Qu'est-ce livre? –

+0

"Apprenez à vous-même les expressions régulières en 10 minutes" – JSON

+0

Pour quiconque lit cette question, notez que le paquet java standard pour les expressions régulières 'java.util.regex' ne prend pas en charge les conditionnelles dans les expressions régulières. –

Répondre

3

La syntaxe est correcte. Le regard étrange (? ....) met en place un conditionnel. C'est la syntaxe d'expression régulière pour une instruction if ... then. Le (1) est une référence arrière au groupe de capture au début de la regex, qui correspond à une balise <html>, s'il y en a une puisque ce groupe de capture est facultatif. Puisque la référence arrière à la balise capturée suit la partie "if" de l'expression rationnelle, ce qu'elle fait est de s'assurer qu'une < étiquette > a été capturée avant d'essayer de correspondre à celle de fermeture. Une façon assez intelligente de rendre les deux balises facultatives, mais en forçant les deux quand la première existe. C'est ainsi qu'il est possible de faire correspondre toutes les lignes dans le texte d'exemple même si certaines d'entre elles ont juste des balises <img>. En ce qui concerne les raisons pour lesquelles une exception est générée dans votre cas, il est fort probable que la saveur de regex que vous utilisez ne prenne pas en charge les conditionnelles. Pas tous.

EDIT: Voici une bonne référence sur les conditions dans les expressions régulières: http://www.regular-expressions.info/conditional.html

+0

regardez le "(<[Aa]\s+[^>] +> \ s *)?" donc est optionnel, si le texte a juste , le? (1) retournera faux, ne s'excutera pas – JSON

+0

Oui, exactement. J'ai modifié ma réponse pour inclure un lien vers une excellente ressource sur les conditions générales de regex. – Bryan

1

Pourrait-il être un groupe non de capture comme décrit ici:

Il y a aussi un groupe spécial, groupe 0, qui a toujours représente l'intégralité de l'expression . Ce groupe n'est pas inclus dans le total indiqué par groupCount. groupes commençant par (? Sont purs, groupes non-capture qui ne sont pas texte de capture et ne comptent pas pour le total du groupe. (Vous verrez des exemples de groupes non-capture plus tard dans la section Méthodes du classe Pattern)

Java Regex Tutorial

1

La réponse courte:. cela ne signifie rien.Le problème réside dans cet extrait tout:

(?(1)\s*) 

() crée une référence arrière, de sorte que vous pouvez réutiliser tout texte correspondant à l'intérieur. Ils vous permettent également d'appliquer des opérateurs à tout ce qui est à l'intérieur d'eux (mais cela n'est pas fait dans votre exemple).

? signifie que l'élément devant lui doit correspondre si c'est là mais il est également OK si ce n'est pas le cas. Cela n'a tout simplement pas de sens quand il apparaît après (

(:. MoreTextHere) peut être utilisé pour accélérer regexs lorsque vous n'avez pas besoin de réutiliser le texte correspondant Mais ce encore n » t vraiment un sens, pourquoi correspond à 1 lorsque votre entrée est HTML

essayez:

(?:<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+> 

vous ne dit exactement ce que vous essayez de faire correspondre si cette réponse ne vous satisfait pas, s'il vous plaît expliquer ce que vous essayez de faire avec RegEx

+1

Comme l'a dit Bryan, la syntaxe est correcte pour une saveur regex qui supporte les conditionnelles, mais pas Java. –

3

Qu'est-ce que vous cherchez à est une construction conditionnelle, comme l'a dit Bryan et Java ne les supporte pas. L'expression entre parenthèses immédiatement après le point d'interrogation peut en fait être n'importe quelle assertion de largeur nulle, comme un lookahead ou un lookbehind, et pas seulement une référence à un groupe de capture. (Je préfère appeler ces back-affirmations, pour éviter toute confusion. Un retour référence correspond à la même chose que le groupe de capture a fait, mais une contre-affirmation accusé affirme simplement que le groupe de capture correspond quelque chose.)

J'ai appris des choses sur les conditions quand je travaillais en Perl il y a des années, mais je ne les ai jamais manqué en Java. Dans ce cas, par exemple, une simple alternance fera l'affaire:

(?i)<a\s+[^>]+>\s*<img\s+[^>]+>\s*</a]>|<img\s+[^>]+> 

Un avantage de la version conditionnelle est que vous pouvez capturer la balise IMG avec un groupe de capture unique:

(?i)(<a\s+[^>]+>\s*)?(<img\s+[^>]+>)(?(1)\s*</a>) 

En la version d'alternance vous devez avoir un groupe de capture pour chaque alternative, mais ce n'est pas aussi important dans Java que dans Perl, avec toute sa magie regex intégrée.Voici comment je voudrais cueillir les balises IMG en Java:

Pattern p = Pattern.compile(
    "<a\\s+[^>]+>\\s*(<img\\s+[^>]+>)\\s*</a>|(<img\\s+[^>]+>)" 
    Pattern.CASE_INSENSITIVE); 
Matcher m = p.matcher(s); 
while (m.find()) 
{ 
    System.out.println(m.start(1) != -1 ? m.group(1) : m.group(2)); 
} 
+0

Bon point sur la différence entre back-reference et back-assertion. En outre, +1 pour fournir une solution en utilisant l'alternance. – Bryan