web-dev-qa-db-fra.com

std :: regex, pour faire correspondre le début/la fin de la chaîne

Dans les expressions régulières JS, les symboles ^ et $ désignent début et fin de la chaîne . Et seulement avec le modificateur /m (mode multiligne), ils correspondent à début et fin de ligne - position avant et après CR/LF.

Mais dans std :: regex / Les symboles du mode ECMAscript ^ et $ correspondent début et fin de ligne toujours.

Est-il possible dans std :: regex de définir le début et la fin de la chaîne des points de correspondance? En d'autres termes: supporter le mode JavaScript multiligne ...

11
c-smile

Par défaut, le mode ECMAscript traite déjà ^ en début de ligne et début-de-ligne et $ en tant que fin d’entrée et fin de ligne. Il n'y a aucun moyen de les faire correspondre à uniquement début ou à la fin de la saisie, mais il est possible de les faire correspondre à uniquement début ou à la fin de la ligne:

Lors de l'appel de std::regex_match , std::regex_search ou std::regex_replace , il existe un argument de type std::regex_constants::match_flag_type dont la valeur par défaut est std::regex_constants::match_default.

  • Pour spécifier que ^ ne correspond qu'au début de la ligne, spécifiez std::regex_constants::match_not_bol
  • Pour spécifier que $ ne correspond qu'à la fin de ligne, spécifiez std::regex_constants::match_not_eol
  • Comme ces valeurs sont des drapeaux bits, pour spécifier les deux, il suffit de les placer côte à côte (std::regex_constants::match_not_bol | std::regex_constants::match_not_eol)
  • Notez que début d'entrée peut être implicite sans utiliser ^ et indépendamment de la présence de std::regex_constants::match_not_bol en spécifiant std::regex_constants::match_continuous

Ceci est bien expliqué dans la documentation de grammaire ECMAScript sur cppreference.com , ce que je recommande vivement à cplusplus.com en général.

Avertissement: j'ai testé avec MSVC, Clang + libc ++ et Clang + libstdc ++, et seul MSVC a le comportement correct à l'heure actuelle.

6
ildjarn

Les ^ et $ correspondent au début et à la fin du string , pas une ligne. Voir cette démo qui ne trouve aucune correspondance dans "1\n2\n3" avec ^\d+$ regex. Lorsque vous ajoutez des alternatives (voir ci-dessous), il y a 3 correspondances .

std::regex ne permet pas de faire correspondre les ancres au début/à la fin de la ligne. Vous devez l'imiter avec des alternances:

^ -> (^|\n)
$ -> (?=\n|$)

Notez que $ peut être "émulé" entièrement avec (?=\n|$) (où vous pouvez ajouter plus de symboles de terminaison de ligne ou de séquences de symboles, comme (?=\r?\n|\r|$)), mais avec ^, vous ne pouvez pas trouver une solution de contournement à 100%.

Comme il n'y a pas de support lookbehind, vous devrez peut-être ajuster d'autres parties de votre motif regex à cause de (^|\n), comme utiliser la capture de groupes plus souvent qu'avec un support lookbehind.

4
Wiktor Stribiżew

L'extrait de code suivant correspond aux adresses électroniques commençant par [a-z], suivies de 0 ou 1 point, puis de 0 ou plusieurs lettres a-z, se terminant par "@ gmail.com". Je l'ai testé.

string reg = "^[a-z]+\\.*[a-z]*@gmail\\.com$";

regex reg1(reg, regex_constants::icase);
reg1(regex_str, regex_constants::icase);
string email;
cin>>email;
if (regex_search(email, reg1))
0
Charlie