Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Помогите составить регулярное выражение, пожалуйста.
Форумы портала PHP.SU » PHP » Регулярные выражения » Помогите составить регулярное выражение, пожалуйста.

Страниц (1): [1]
 

1. Phobos - 16 Февраля, 2008 - 18:02:15 - перейти к сообщению
Здравствуйте!
Встал довольно срочный вопрос. В общем никак немогу составить правильно регулярное выражение на PHP.
Суть такая.
Есть некое количество переменных значений в фиг. скобках, в свою очередь в этих скобках могут быть ещё фигурные скобки. Таким образом, получается вложеннось. Но вложенность не может быть больше 1-го уровня, что естественно задачу облегчает. НО. Принципиально важно, чтобы в фиг. скобках вложенными были только фиг. скобки, а не какие другие делимиторы.

Вот пример исходной строки:

Основное {Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|} Значение 4{Значение 4.1|Значение 4.2|Значение 4.3|} Значение 5} Основное 2

Суть в том, что мне нужно получть отдельно:
- {Значение 1|Значение 2|Значение 3
- {Значение 3.1|Значение 3.2|Значение 3.3|}
- Значение 4
- {Значение 4.1|Значение 4.2|Значение 4.3|}
- Значение 5
и потом уже дальше с ними манипулировать.

Пробую preg_match_all("~\{(.*)\}~isU", $stroka, $fVarsArray, PREG_PATTERN_ORDER)
Где $stroka - исходная строка, $fVarsArray - массив того, что находит.
Но находит не то.
Вместо 1-го значения оно мне выдаёт {Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|}, а не {Значение 1|Значение 2|Значение 3

Подскажите, как мне быть.
2. scuter - 17 Февраля, 2008 - 02:06:08 - перейти к сообщению
есть такие интересные функции,
http://www.php.su/functions/?explode
http://www.php.su/functions/?implode
но суде по всему вам нужно не это а перевести данные из JSON формата,
http://framework[dot]zend[dot]com/manual[dot][dot][dot]u/zend[dot]json[dot]html
3. Phobos - 17 Февраля, 2008 - 03:22:39 - перейти к сообщению
scuter пишет:
есть такие интересные функции,
http://www.php.su/functions/?explode
http://www.php.su/functions/?implode

Эти интересные функции я знаю прекрасно Улыбка Но они мне здесь не помогут (хотя в целом в проге применяются) Улыбка

Я же писал конкретно что нужно:
Цитата:

Суть в том, что мне нужно получть отдельно:
- {Значение 1|Значение 2|Значение 3
- {Значение 3.1|Значение 3.2|Значение 3.3|}
- Значение 4
- {Значение 4.1|Значение 4.2|Значение 4.3|}
- Значение 5
и потом уже дальше с ними манипулировать.

А как составить рег. выр., ну не въеду уже 2-й день. Просто логически немогу догадаться. Как можно скрипту объяснить - где у открывающейся скобки именно её закрывающая, а не первая попавшаяся по строке?.. Ниндзя
Самое интересное - это же как-то реализовано в той же моей любимой Zend Studio: ставишь курсор перед скобкой а он тнбн ПРАВИЛЬНО определяет её закрывающую (или наоборот). Это не к тому, что я хочу интерпретатор ПХП на ПХП писать, просто суть похожая.
4. evgenijj - 17 Февраля, 2008 - 17:47:48 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1. $text = "
  2. Основное {Значение 1|Значение 2|Значение 3
  3. {Значение 3.1|Значение 3.2|Значение 3.3|}
  4. Значение 4{Значение 4.1|Значение 4.2|Значение 4.3|}
  5. Значение 5} Основное 2";
  6. preg_match_all( '#\{(.+)\}#s', $text, $matches );
  7. $txt = $matches[1][0];
  8. unset( $matches );
  9. preg_match_all( '#\{.+?\}#s', $txt, $matches );
  10. $tmp = $matches[0];
  11. $cnt = count( $tmp );
  12. for ( $i = 0; $i < $cnt; $i++ ) {
  13.   $ids[$i] = 'array_'.$i;
  14.   $txt = str_replace( $tmp[$i], '@'.$ids[$i].'@', $txt );
  15. }
  16. $txt = str_replace( '|', '@', $txt );
  17. for ( $i = 0; $i < $cnt; $i++ ) {
  18.   $txt = str_replace( $ids[$i], $tmp[$i], $txt );
  19. }
  20. $res = explode( '@', $txt );
  21. foreach( $res as $value ) echo $value.'<br/>';
5. Phobos - 22 Февраля, 2008 - 04:26:59 - перейти к сообщению
evgenijj

Спасибо!

Однако это немного не то. Возможно я просто неправильно или как-то непонятно объяснил.
С Вашим кодом получается так, что если в исходное значение добавить ещё переменных в скобках, то уже ничего не работает правильно.

Просто в задаче заранее неопределено - сколько будет в тексте вхождений скобок с вложенными скобками (и сколько в них будет вложенных) и сколько обычных 1-го уровня.

Я решил всетаки эту задачу, однако без регулярных выражений вообще. Чисто на элементарных функциях PHP. Однако может я и неправильно поступил.
Но самое главное, всё работает!
Вот код:
PHP:
скопировать код в буфер обмена
  1.  
  2. $text = "Основ 1 {Знач 1{3.3|}{} {jhgjhgh} Знач 4{4.3|}ascasc} Основ 2 {Ещё{} кое-что}{Ещё{} кое-что} [] {} {{}}";
  3.  $text2= $text;
  4.  
  5.     //Ищем пару скобке.
  6.     for ($i=0; $i<=substr_count($text2, '}')-1; $i++)
  7.     {
  8.       $msoppos = strpos($text, '{');
  9.       $msclpos = strpos($text, '}');//Находим позицию 1-й }
  10.       //Если между откр (::main~ и найденым } количество откр. равно кол-ву закр. подскобок, то принимаем за главную и закрываем (заменяем на усл. знак.), если нет то дальше
  11.       $buffer = substr($text, $msoppos+1, $msclpos-$msoppos-1);
  12.       //Счит. кол-во { и }
  13.       $socnt = substr_count($buffer, '{');
  14.       $sccnt = substr_count($buffer, '}');
  15.       $ssccnt = substr_count($buffer, '~sub::)');
  16.      
  17.       if ($socnt == $sccnt or $socnt == $ssccnt)//Если количество открывающих и закрывающих внутри равны, то значит наша закрывающая есть главная!!! УРА!!!
  18.       {
  19.         //Заменяем значения, чтобы к ним уже не возвращаться! Уффффф.
  20.         $msoppos = strpos($text, '{');        
  21.         $text = substr_replace($text, '(::main~', $msoppos, 1);//Заменяем { на (::main~
  22.        
  23.         $msclpos = strpos($text, '}');//Находим позицию 1-й }
  24.         $text = substr_replace($text, '~main::)', $msclpos, 1);//Заменяем } на ~main::)
  25.        
  26.         //Теперь все внутренние закр. скобки заменяем на усл. знак. (::sub~
  27.         $buffer2 = substr($text, $msoppos, $msclpos-$msoppos);
  28.         $buffer3 = str_replace('{', '(::sub~', $buffer2);
  29.         $text = str_replace($buffer2, $buffer3, $text);
  30.  
  31.       }
  32.       else
  33.       {
  34.         $text = substr_replace($text, '~sub::)', $msclpos, 1);//Заменяем } на ~main::)
  35.       }
  36.     }
  37.  
  38. echo '<b>'.$text.'<br>';
  39.  

Но сразу оговорюсь, что он только часть функции выполняет, а именно делает отличие между вложенными скобками и скобками 1-го уровня. Это самое главное было. А когда они различны - уже просто дальше их выделить, и выделить все значения из них.

Спасибо за внимание и ответы!!! Подмигивание

P.S. Не серчайте, что код кривоватый. Пол ночи писал, и спать ужо охота!!! Улыбка
6. evgenijj - 22 Февраля, 2008 - 08:44:34 - перейти к сообщению
Phobos пишет:
Но вложенность не может быть больше 1-го уровня

Phobos пишет:
если в исходное значение добавить ещё переменных в скобках, то уже ничего не работает правильно.
7. Phobos - 25 Февраля, 2008 - 18:51:13 - перейти к сообщению
evgenijj пишет:
Phobos пишет:
Но вложенность не может быть больше 1-го уровня

Phobos пишет:
если в исходное значение добавить ещё переменных в скобках, то уже ничего не работает правильно.


Тут нет противоречия. Я имел ввиду добавить рядом значение, а не внутрь, не изменяя уровень вложенности:

{1|2|3{3.1|3.2|.3.3}}
или
{1|2|3{3.1|3.2|.3.3}4{4.1|4.2|.4.3}}
или
{1|2|3{3.1|3.2|.3.3}4{4.1|4.2|.4.3}}5{5.1}

Вот какие случаи. тоесть вложенность не больше 1-го.
Видимо я просто плохо сформулировал задачу.

Спасибо.

 

Powered by ExBB FM 1.0 RC1