0
$file = '{include file="{$COMMON_TPL_PATH}common/header_admin.tpl"}
{include file="{$mainPage}"}
{include file="{$COMMON_TPL_PATH}common/footer_admin.tpl"}';
preg_match('/^(\{\})|^(\{\*([\S\s]*?)\*\})|^(<\?(?:php\w+|=|[a-zA-Z]+)?)|^([     ]*[
]+[  ]*)|^(\{strip\})|^(\{\/strip\})|^(\{literal\})|^(\{\s{1,}\/)|^(\{\s{1,})|^(\{\/)|^(\{)|^(([\S\s]*?)(?=([    ]*[
]+[  ]*|\{|<\?)))|^([\S\s]+)/', $file, $matches);
var_dump($matches);

Why the output is:

array(13) {
  [0]=>
  string(1) "{"
  [1]=>
  string(0) ""
  [2]=>
  string(0) ""
  [3]=>
  string(0) ""
  [4]=>
  string(0) ""
  [5]=>
  string(0) ""
  [6]=>
  string(0) ""
  [7]=>
  string(0) ""
  [8]=>
  string(0) ""
  [9]=>
  string(0) ""
  [10]=>
  string(0) ""
  [11]=>
  string(0) ""
  [12]=>
  string(1) "{"
}

It seems to me that ^([\S\s]+) can match the whole string..

smarty
  • 5
  • 2
  • You are right about `[\s\S]`. See this http://stackoverflow.com/questions/4544636/what-does-s-s-mean-in-regex-in-php – codaddict Dec 29 '10 at 07:35

1 Answers1

1

The reason is that group 12 (^(\{)) matches successfully, and therefore the regex engine stops. It never even gets to try to match group 16 (^([\S\s]+)).

If you put group 16 before group 12, then it will match the entire string. However, since [\s\S] matches any character at all (and can be abbreviated to . when using the s modifier), then none of the other groups will ever match.

All in all, your regex looks quite weird. I wouldn't be surprised if it contained a few bugs aside from the obvious warts like trying to put several spaces into a single character class.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • BTW,what does `(?=` mean in the above regex? – smarty Dec 29 '10 at 07:54
  • `(?=...)` is a positive lookahead. It asserts that it is possible to match its contents at the current position without actually adding those characters to the match. So `foo(?=bar)` will match `foo` only if it is followed by `bar`. – Tim Pietzcker Dec 29 '10 at 08:07