2009-08-25 6 views
2

Я пытаюсь соответствовать строке, как это:Регулярного выражения для разбора данных трубных разделителей, заключенные в двойном фигурных

{{name|arg1|arg2|...|argX}} 

с регулярным выражением

Я использую preg_match с

/{{(\w+)\|(\w+)(?:\|(.+))*}}/ 

но я получаю что-то вроде этого, когда я использую более двух аргументов

Array 
(
    [0] => {{name|arg1|arg2|arg3|arg4}} 
    [1] => name 
    [2] => arg1 
    [3] => arg2|arg3|arg4 
) 

Первые два элемента не могут содержать пробелы, а остальные могут. Возможно, я слишком долго работаю над этим, но я не могу найти ошибку - любая помощь будет принята с благодарностью.

Спасибо Jan

ответ

4

Не использовать регулярные выражения для такого рода простых задач. Что вам действительно нужно:

$inner = substr($string, 2, -2); 
$parts = explode('|', $inner); 

# And if you want to make sure the string has opening/closing braces: 
$length = strlen($string); 
assert($inner[0] === '{'); 
assert($inner[1] === '{'); 
assert($inner[$length - 1] === '}'); 
assert($inner[$length - 2] === '}'); 
+1

Хорошо, я должен уточнить то:
Я пытаюсь соответствовать неизвестное количество указанных выражений на странице HTML шаблона. , поэтому простой субстрат не является возможным ...
но вы дали мне идею;) Я буду использовать регулярное выражение, чтобы найти {{([^}] +)}}, а затем продолжить взрыв. Спасибо! – Jan

+0

Это довольно ленивый ответ и превращает простую задачу в запись миллиона чеков, если вы действительно хотите быть уверенными. И вместо того, чтобы зачищать скобки с помощью подстроки, почему бы не сделать str_replace (array ('{', '}'), '', $ string); –

+0

Этот ответ был написан до разъяснения. И использование str_replace() не позволяет вам ** проверить **, что скобки находятся в строке. – soulmerge

0

Должно работать на любом месте от 1 до N аргументы

<?php 

$pattern = "/^\{\{([a-z]+)(?:\}\}$|(?:\|([a-z]+))(?:\|([a-z ]+))*\}\}$)/i"; 

$tests = array(
    "{{name}}"       // should pass 
    , "{{name|argOne}}"     // should pass 
    , "{{name|argOne|arg Two}}"   // should pass 
    , "{{name|argOne|arg Two|arg Three}}" // should pass 
    , "{{na me}}"       // should fail 
    , "{{name|arg One}}"     // should fail 
    , "{{name|arg One|arg Two}}"   // should fail 
    , "{{name|argOne|arg Two|arg3}}"  // should fail 
); 

foreach ($tests as $test) 
{ 
    if (preg_match($pattern, $test, $matches)) 
    { 
    echo $test, ': Matched!<pre>', print_r($matches, 1), '</pre>'; 
    } else { 
    echo $test, ': Did not match =(<br>'; 
    } 
} 
3

Проблема находится здесь: \ | (. +)

Регулярные выражения, по по умолчанию, как можно больше символов. Поскольку . любой символ, другие экземпляры | тоже счастливы, что вам не нравится.

Чтобы этого избежать, вы должны исключить | из выражения, говорящего «соответствовать чему угодно, кроме |», в результате чего \ | ([^ \ |] +).

0

Конечно, вы получите что-то вроде этого :) В регулярном выражении нет способа вернуть динамическое количество совпадений - в вашем случае аргументы.

Глядя на то, что вы хотите сделать, вы должны идти в ногу с текущим регулярным выражением и просто взорвать дополнительные аргументы на '|' и добавить их в массив args.

0

на самом деле, это от PCRE инструкции:

Когда подмаска повторяется , значение захватили является подстроку, которая соответствует окончательной итерации. Например, после (tweedle [dume] {3} \ s *) + соответствует «tweedledum tweedledee» значение захваченная подстрока равна «tweedledee». Однако, если есть вложенные подпанели вложенных захватов, то соответствующие захваченные значения могут быть установлены в предыдущих итерациях . Для примера , после/(a ​​| (b)) +/соответствует «aba» значение второго захваченного подстроки «b».

 Смежные вопросы

  • Нет связанных вопросов^_^