Привет всем! В PHP имеется строка примерно такого вида:
$string = 'random text {cmdType:cmdExpression} random text {cmdType:if(true){do something;}do something else;} {cmdType:cmdExpression} random text';
Нужно регулярное выражение для ф-ии preg_match_all, чтобы вычленить все блоки вида {cmdType:cmdExpression}.
Здесь cmdType - это просто какая-то строка, обозначающая тип команды (что-то вроде «regexp», «php» и пр)
cmdExpression - это какой-то код (непосредственно код php, регулярное выражение или что-то ещё).
Составил вот такое:
$regex = '#{([^:]+):(.*)}(?=([^}]*\{\w+\:|$|[^{}]+$))#iU';
$r = preg_match_all($regex, $string, $matches);
var_dump($r);
Возвращает в данном случае примерно такой результат:
array(4) {
  [0]=>
  array(3) {
    [0]=>
    string(23) "{cmdType:cmdExpression}"
    [1]=>
    string(50) "{cmdType:if(true){do something;}do something else}"
    [2]=>
    string(23) "{cmdType:cmdExpression}"
  }
  [1]=>
  array(3) {
    [0]=>
    string(7) "cmdType"
    [1]=>
    string(7) "cmdType"
    [2]=>
    string(7) "cmdType"
  }
  [2]=>
  array(3) {
    [0]=>
    string(13) "cmdExpression"
    [1]=>
    string(40) "if(true){do something;}do something else"
    [2]=>
    string(13) "cmdExpression"
  }
  [3]=>
  array(3) {
    [0]=>
    string(22) " random text {cmdType:"
    [1]=>
    string(10) " {cmdType:"
    [2]=>
    string(12) " random text"
  }
}
Всё прекрасно работает, вот только минус в том, что в части «random text» не должны встречаться фигурные скобки, поскольку тогда логика работы моего регулярного выражения нарушается. Например (добавлена закрывающая фигурная скобка во второй блок random text):
$string2 = 'random text {cmdType:cmdExpression} random } text {cmdType:if(true){do something;}do something else} {cmdType:cmdExpression} random text';
$regex = '#{([^:]+):(.*)}(?=([^}]*\{\w+\:|$|[^{}]+$))#iU';
$r = preg_match_all($regex, $string, $matches);
var_dump($r);
Выводит:
array(4) {
  [0]=>
  array(3) {
    [0]=>
    string(32) "{cmdType:cmdExpression} random }"
    [1]=>
    string(50) "{cmdType:if(true){do something;}do something else}"
    [2]=>
    string(23) "{cmdType:cmdExpression}"
  }
  [1]=>
  array(3) {
    [0]=>
    string(7) "cmdType"
    [1]=>
    string(7) "cmdType"
    [2]=>
    string(7) "cmdType"
  }
  [2]=>
  array(3) {
    [0]=>
    string(22) "cmdExpression} random "
    [1]=>
    string(40) "if(true){do something;}do something else"
    [2]=>
    string(13) "cmdExpression"
  }
  [3]=>
  array(3) {
    [0]=>
    string(15) " text {cmdType:"
    [1]=>
    string(10) " {cmdType:"
    [2]=>
    string(12) " random text"
  }
}
Вместо первого «{cmdType:cmdExpression}» получили «{cmdType:cmdExpression} random }». Так не хотелось бы. Кто-нибудь может помочь составить вариант выражения, который обходит это ограничение (позволяет использовать фигурные скобки в части random text)?


