3 votes

Expressions régulières en PHP. Obtenir le texte entre les parenthèses du premier niveau

J'ai deux types de chaînes dans un texte :

a(bc)de(fg)h

a(bcd(ef)g)h

Je dois obtenir le texte entre les parenthèses de premier niveau. Dans mon exemple, il s'agit de :

bc

fg

bcd(ef)g

J'ai essayé d'utiliser l'expression régulière suivante /\((.+)\)/ avec le drapeau Ungreedy (U) :

bc

fg

bcd(ef

Et sans :

bc)de(fg

bcd(ef)g

Les deux variantes ne font pas ce dont j'ai besoin. Peut-être que quelqu'un sait comment résoudre mon problème ?

1voto

Robin Mackenzie Points 11206

Cette question a pratiquement la réponse, mais les implémentations sont un peu ambiguës. Vous pouvez utiliser la logique de la réponse acceptée sans les ~ pour obtenir cette regex :

\(((?:\[^\(\)\]++|(?R))*)\)

Testé avec cette sortie :

entrez la description de l'image ici

1voto

RomanPerekhrest Points 54365

Utilisez PCRE modèle récursif pour faire correspondre des sous-chaînes dans des parenthèses imbriquées :

$str = "a(bc)de(fg)h some text a(bcd(ef)g)h ";
preg_match_all("/\((((?>[^()]+)|(?R))*)\)/", $str, $m);

print_r($m[1]);

La sortie :

Array
(
    [0] => bc
    [1] => fg
    [2] => bcd(ef)g
)

\( ( (?>[^()]+) | (?R) )* \)

D'abord, il fait correspondre une parenthèse ouvrante. Ensuite, il correspond à un nombre quelconque de sous-chaînes qui peuvent être soit une séquence de caractères non parenthèses, soit une correspondance récursive avec le modèle lui-même (c'est-à-dire une sous-chaîne correctement parenthésée). Enfin, il y a une parenthèse fermante.


Précautions techniques:

S'il y a plus de 15 parenthèses capturantes dans un modèle, PCRE doit obtenir de la mémoire supplémentaire pour stocker des données pendant une récursion, ce qu'il fait en utilisant pcre_malloc, en le libérant via pcre_free par la suite. Si aucune mémoire ne peut être obtenue, il ne sauvegarde des données que pour les 15 premières parenthèses capturantes, car il n'y a pas de moyen de générer une erreur de mémoire insuffisante à partir d'une récursion.

-1voto

kodmanyagha Points 96

S'il vous plaît pouvez-vous essayer cela:

preg_match("/\((.+)\)/", $input_line, $output_array);

Testez ce code dans http://www.phpliveregex.com/

Regex: \((.+)\)
Input: a(bcd(eaerga(er)gaergf)g)h
Output: array(2
   0    =>  (bcd(eaerga(er)gaergf)g)
   1    =>  bcd(eaerga(er)gaergf)g
)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X