Expression régulière pour ignorer le caractère dans le groupe de capture

Est-il possible d'ignorer quelques caractères dans un groupe de capture dans des expressions régulières? J'utilise des expressions rationnelles. net mais cela ne devrait pas avoir d'importance.

Fondamentalement, ce que je cherche est:

[texte aléatoire]AB-123[texte aléatoire]

Et j'ai besoin de capturer 'AB123', sans le trait d'Union.

Je sais que AB est 2 ou 3 caractères majuscules et 123 est 2 ou 3 chiffres, mais ce n'est pas la partie difficile. La partie difficile (au moins pour moi) est de sauter le trait d'Union.

Je je suppose que je pourrais capturer les deux séparément, puis les concaténer dans le code, mais j'aimerais avoir une solution plus élégante, uniquement regex.

Des suggestions?

33
demandé sur Tamas Czinege 2008-11-10 13:31:15

5 réponses

En bref: vous ne pouvez pas. une correspondance est toujours consécutive, même quand elle contient des choses comme des assertions de largeur nulle, il n'y a aucun moyen de faire correspondre le caractère suivant si vous voulez arriver à celui qui suit.

42
répondu Tomalak 2008-11-10 10:38:49

Il n'y a vraiment pas moyen de créer une expression telle que le texte correspondant soit différent de ce qui se trouve dans le texte source. Vous devrez supprimer le trait d'Union dans une étape distincte soit en faisant correspondre les première et deuxième parties individuellement et en concaténant les deux groupes:

match = Regex.Match( text, "([A-B]{2,3})-([0-9]{2,3})" );
matchedText = string.Format( "{0}{1}", 
    match.Groups.Item(1).Value, 
    match.Groups.Item(2).Value );

Ou en supprimant le trait d'union dans une étape distincte du processus d'appariement:

match = Regex.Match( text, "[A-B]{2,3}-[0-9]{2,3}" );
matchedText = match.Value.Replace( "-", "" );
16
répondu Jeff Hillman 2008-11-10 10:45:50

Votre affirmation selon laquelle il n'est pas possible de le faire sans sous-regroupement + concatenting est correcte.

Vous pouvez également faire comme Jeff-Hillman et simplement enlever le(s) mauvais personnage (s) après le fait.

Important de noter ici, est-ce que vous "n'utilisez pas regex pour tout".

Regex est conçu pour des solutions moins compliquées pour des problèmes non triviaux, et vous ne devriez pas utiliser "oh, nous allons utiliser une regex" pour tout, et vous ne devriez pas entrer dans le habbit de penser que vous pouvez résoudre le problème dans une regex en une étape.

Quand il y a une méthode triviale viable qui fonctionne, par tous les moyens, utilisez-la.

Une autre idée, si vous avez besoin de retourner plusieurs correspondances dans un corps de code est de rechercher votre regex basée sur le "callback" des langues, ce qui permet de passer tout groupe apparié/trouvé à un appel de fonction qui peut faire une substitution en ligne. (Particulièrement pratique pour faire des remplacements regexp).

Je ne sais pas comment cela fonctionnerait dans. Net, mais en php vous feriez quelque chose comme (Code pas exact)

  function strip_reverse( $a )
  {
     $a = preg_replace("/-/", "", $a );
     return reverse($a);
  }
  $b = preg_replace_callback( "/(AB[-]?cde)/" , 'strip_reverse' , "Hello World AB-cde" ; 
4
répondu Kent Fredric 2008-11-10 10:58:36

Vous pouvez utiliser des groupes de capture imbriqués, comme ceci:

((AB)-(123))

, Le premier groupe de capture est AB-123, le second est de AB, et la troisième est 123. Ensuite, tout ce que vous auriez à faire est de rejoindre le deuxième et le troisième groupe avec un espace.

1
répondu Steve 2015-11-21 19:09:45

Un peu tard, mais je pense que j'ai compris celui-ci. Au moins un moyen de le faire.

J'ai utilisé lookahead positif pour m'arrêter au signe # dans mon texte. Je ne voulais pas l'espace ou le signe#, donc j'ai dû trouver un moyen de "sauter" sur eux. Donc, quand j'ai été forcé de les faire correspondre à nouveau, je les ai jetés dans un groupe de déchets que je n'avais pas l'intention d'utiliser (. ie, un seau de bits) qui dans le code est . Maintenant, mon pointeur de place est une position de caractère au-delà du signe # (où je veux être, en sautant le l'espace et le signe#). Et je maintenant juste correspondre à la fin du nom de fichier à la . et d'ignorer l'extension de fichier.

(?i)English\\(?<Series>[^ ]+) - (?<Title>.+(?= #))(?<garb1>..)(?<Number>[^.]+)(?-i)

Le nom de fichier sur lequel il a été utilisé est

F:\Downloads\Downloads\500 Comics CCC CBR English\Isukani - Great Girl #01.cbr
0
répondu Logan9773 2018-01-27 13:54:29