dongpu9481
2012-12-12 07:48 阅读 22
已采纳

php preg_match可选子模式

i try to build a small system that catches variables from html template.

the variables defined as @XXX@ and may (but not required) to have extra parameters that are sent with colon (:), i.e. @XXX@:j to send the data as json encoded.

what i manage to do is to create a preg_match_all to capture the variables and those extra parameters. so i came up with this preg:

preg_match_all("/(@.*@(?:(j|n|x|z))?)/imU", $string,$this->localVariables,PREG_PATTERN_ORDER);

j|n|x|z are the avialiable extra parameters that are possible.

the string that i send to $string is: @geterr@ @domain@:j @jhon@:n

the result i get from preg_match_all is:

Array
(
[0] => Array
    (
        [0] => @geterr@
        [1] => @domain@
        [2] => @jhon@
    )

[1] => Array
    (
        [0] => @geterr@
        [1] => @domain@
        [2] => @jhon@
    )

[2] => Array
    (
        [0] => 
        [1] => 
        [2] => 
    )

)

i know (or think i know) that ?: is used for optional sub pattern the modifires iv'e used are: i for case insensitive m for to allow my string to be multiline U - to be non greedy

i have no other clue what i do wrong.

any help shall be greatly appriciated

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    dpnru86024 dpnru86024 2012-12-12 08:12

    There are some issues in your pattern /(@.*@(?:(j|n|x|z))?)/imU

    1. You don't need a capturing group around the whole pattern.

    2. ?: is creating a non capturing group, it is not limited to optional groups.

    3. The modifier m is called multiline, but this is a bit misleading it affects only the anchors ^ and $ to match also the start and end of a row and not only of the string.

      What you want is the modifier s, the singleline modifier. It treats the whole string as one line, and affects the . to match also newline characters.

    4. The modifier U makes your whole regex ungreedy. This is not what you want, because it affects also your optional group and because it is at the end of the pattern it will never match.

    5. You need to match the : in your string

      So I would remove U and make only the first quantifier ungreedy, by adding a ? after it.

    So I think your regex should be:

    /@(.*?)@(?::(j|n|x|z))?/is
    

    This would put the first part between the @ in the first capturing group and the parameter in the second group.

    See it here on Regexr

    点赞 评论 复制链接分享

相关推荐