8
votes

C # Match d'expression régulière à l'index spécifique de la chaîne?

J'aimerais tester si une regex correspondra à une partie d'une chaîne à un index spécifique (et ne commençant qu'à cet indice spécifique). Par exemple, étant donné la chaîne "une deux 3 4 cinq", j'aimerais savoir que, à l'index 8, l'expression régulière [0-9] + correspondra "3". Regularexpression.Actralisez et assumez les deux prenons un index de départ, mais ils rechercheront tous les deux la totalité du reste de la chaîne pour une correspondance si nécessaire. XXX

Évidemment, je pouvais vérifier si la correspondance résultante commence à L'indice que je suis intéressé, mais je vais le faire un grand nombre de fois sur de grandes chaînes. Je ne veux donc pas perdre de temps à rechercher des correspondances plus tard dans la chaîne. En outre, je ne saurai pas à l'avance quelles expressions régulières je vais réellement tester contre la chaîne.

Je ne veux pas:

  1. diviser la corde sur certaines limites comme Whitespace parce que dans mon situation que je ne saurai pas à l'avance Quelle limite appropriée serait
  2. doit modifier la chaîne d'entrée dans Toute façon (comme obtenir la sous-chaîne à l'index 8 puis en utilisant ^ dans le regex)
  3. Rechercher dans le reste de la chaîne pour une correspondance ou faire n'importe quoi sinon ce ne serait pas performant pour un grand nombre de tests contre un Grande chaîne.

    Je voudrais analyser un corps potentiellement important fourni par un utilisateur de texte à l'aide d'une grammaire fournie par l'utilisateur arbitraire. La grammaire sera définie dans une syntaxe BNF ou PEG comme une syntaxe, et les terminaux seront des littéraux strings ou des expressions régulières. Ainsi, je devrai vérifier si la partie suivante de la chaîne correspond à l'un des terminaux potentiels comme entraînement par la grammaire.


2 commentaires

Pouvez-vous expliquer ce que vous essayez de faire dans un sens plus large? Vos restrictions sur ce que vous ne voulez pas faire sont déroutants.


J'ai ajouté une brève description de ce que je fais. De plus, les exigences reviennent vraiment à: Je ne veux pas faire de rien de lent et je n'ai pas la connaissance approfondie de ce que j'essaie d'analyser à l'avance.


4 Réponses :


13
votes

Que diriez-vous d'utiliser regex.Amatch (chaîne, int) à l'aide d'une expression régulière commençant par \ g (signification "Début du dernier match")?

que semble fonctionner: xxx


3 commentaires

Intéressant, s'il y a un moyen de définir artificiellement la dernière position de match, cela pourrait s'entraîner. Sinon, je ne pense pas que cela aidera parce que je vais sauter entre différentes expressions régulières et différents endroits.


J'ai eu une chance d'essayer cela et il semble faire exactement ce que je veux. Il traite l'indice de démarrage passé comme le «Début du dernier match», quel que soit l'endroit où se trouvait le dernier match. Parfait merci!


Et juste pour ajouter un peu d'informations pour quelqu'un d'autre qui a ce problème, régulier-expressions.info/ continuer.html décrit l'ancre \ g. Il semble que ce soit «début du dernier match» ou «début de tentative de match» en fonction de la mise en œuvre. Dans certaines implémentations, il ne résoudra probablement pas ce problème, mais il semble être «début de tentative de match» en C # et fonctionne bien pour correspondre à un emplacement spécifique.



2
votes

Si vous souhaitez uniquement rechercher une sous-chaîne du texte, saisissez cette sous-chaîne avant la regex.

myRegex.Match(myString.Substring(8, 10));


5 commentaires

Ne ressemble pas à cela modifie la chaîne d'entrée, donc +1. Si le point 2 ne concerne pas seulement la modification de la chaîne d'entrée, elle doit être modifiée.


Eh bien, il modifie l'entrée à l'expression régulière . Compte tenu de «faire cela un grand nombre de fois sur de grandes chaînes», je n'aurais pas pensé qu'une sous-chaîne était une solution idéale.


On dirait qu'il veut correspondre à une série spécifique de caractères dans une chaîne. Pourquoi ne peut-il pas avoir de sens?


@ROB: Parce que cela impliquera de copier de grandes quantités de données à plusieurs reprises - et inutilement, étant donné que vous pouvez indiquer au moteur de regex où commencer à chercher un match.


Ce serait trop lent car je n'ai aucune longueur maximale autre que la taille de la chaîne, qui pourrait être des dizaines de centaines de mégaoctets.



1
votes

Je ne suis pas sûr que je comprends bien la question, mais il me semble que vous pouvez simplement rendre la position de la position de l'expression régulière, par exemple xxx

qui correspondra s'il y a 8 caractères entre le début de la chaîne et un chiffre.


1 commentaires

Ce n'est pas idéal, car cela impliquerait de modifier la regex pour chaque poste que je souhaite tester. Cela dépendrait également de la regex suffisamment intelligente pour optimiser ^. {8} dans quelque chose qui saute immédiatement à la position 8.



0
votes

Si vous connaissez la longueur maximale d'une correspondance potentielle dans la chaîne, vous devez vérifier que cela limiterait la numérisation de la chaîne.

Si vous ne vérifiez que des chiffres, cela est probablement plus facile que si vous vérifiez les expressions arbitraires. . La nature de la regex est de numériser jusqu'à la fin afin de trouver un match. Si vous souhaitez empêcher la numérisation, vous devez inclure une longueur ou utilisez autre chose que REGEX. P>

string text = "one two 3 4 five";
Regex num = new Regex("[0-9]+");
int indexToCheck = 8;
int maxMatchLength = ...;
Match m = num.Match(text, indexToCheck, maxMatchLength);


2 commentaires

Malheureusement, je ne sais pas quelles expressions régulières seront préalablement et ne peuvent pas fournir une longueur maximale autre que le reste de la chaîne.


L'expression à trouver pourrait avoir une longueur variable, selon WhitSpace E.G. Les nouvelles lignes et en retrait paragraphe commencent, ou autre chose.