Repetición de expersión regular dentro de un patrón

I have the following text and I would like to preg_match_all what is within the {y }'s if it contains only a-zA-Z0-9 y :

some text,{SOMETHING21} {SOMETHI32NG:MORE}some msdf{TEXT:GET:2}sdfssdf sdf sdf

Estoy tratando de igualar {SOMETHING21} {SOMETHI32NG:MORE} {TEXT:GET:2} there can be several :'s within the tag.

Lo que tengo actualmente es:

preg_match_all('/\{([a-zA-Z0-9\-]+)(\:([a-zA-Z0-9\-]+))*\}/', $from, $matches, PREG_SET_ORDER);

It works as expected for {SOMETHING21} y {SOMETHI32NG:MORE} pero para los {TEXT:GET:2} solo coincide TEXT y 2

So it only matches the first and last word within the tag, and leaves the middle ones out of the $matches array. Is this even possible or should I just match them and then explode on : ?

editar

Well the question isn't if I can get the tags, the question is if I can get them grouped without having to explode the results again. Even though my current regex finds all the results the subpattern does not come back with all the matches in $matches.

I hope the following will clear it up abit more:

\{                              // the match has to start with {
([a-zA-Z0-9\-]+)                // after the { the match needs to have alphanum consisting out of 1 or more characters
(
    \:                          // if we have : it should be followed by alphanum consisting out of 1 or more characters
    ([a-zA-Z0-9\-]+)            // <---- !! this is what it is about !! even though this subexpression is between brackets it is not put into $matches if more then one of these is found
)*                              // there could be none or more of the previous subexpression
\}                              // the match has to end with }

preguntado el 09 de marzo de 12 a las 15:03

3 Respuestas

You can't get all the matched values of a capturing group, you only get the last one.

So you have to match the pattern:

preg_match_all('/{([a-z\d-]+(?::[a-z\d-]+)*)}/i', $from, $matches);

and then split each element in $matches[1] on :.

respondido 09 mar '12, 16:03

Need to escape the { curly brace. Otherwise +1 - ridgerunner

@ridgerunner, you don't need to escape { en este caso. - Qimpuesto

I was hoping I could do this without having to explode my $matches[1]. Anyway, thanks for clearing it up. - Jeffreydev

@jeffreydev, .NET regex is the only flavor that you could do that with. But if you have a known limited number of : you could use optional capturing groups if you want. - Qimpuesto

I used non-capture groupings to eliminate the inner groups, and just capture the outer complete colon-separated list.

$from = "some text,{SOMETHING21} {SOMETHI32NG:MORE}some msdf{TEXT:GET:2}sdfssdf sdf sdf";
preg_match_all('/\{((?:[a-zA-Z0-9\-]+)(?:\:(?:[a-zA-Z0-9\-]+))*)\}/', $from, $matches, PREG_SET_ORDER);
print_r($matches);

Resultado:

Array
(
    [0] => Array
    (
        [0] => {SOMETHING21}
        [1] => SOMETHING21
    )

    [1] => Array
    (
        [0] => {SOMETHI32NG:MORE}
        [1] => SOMETHI32NG:MORE
    )

    [2] => Array
    (
        [0] => {TEXT:GET:2}
        [1] => TEXT:GET:2
    )

)

respondido 09 mar '12, 15:03

Maybe I didn't understand the requirement, but...

preg_match_all('/{[A-Za-z0-9:-]+}/', $from, $matches, PREG_PATTERN_ORDER);

resulta en:

Array
(
    [0] => Array
        (
            [0] => {SOMETHING21}
            [1] => {SOMETHI32NG:MORE}
            [2] => {TEXT:GET:2}
        )
)

respondido 09 mar '12, 16:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.