Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите составить регулярное выражение на PHP

420
16 февраля 2008 года
Fobos
197 / / 10.03.2006
Здравствуйте!
Встал довольно срочный вопрос. В общем никак немогу составить правильно регулярное выражение на 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

Подскажите, как мне быть.
420
16 февраля 2008 года
Fobos
197 / / 10.03.2006
Я в принципе не знаю. Может я чересчур загнался?
Хотя поидее так возможно сделать. В той же программе Zend Studio в редакторе кода правильно определяется какая открывающая скобка к какой именно закрывающей относится. В принципе, похожая ерунда. Но как их определить? Или лучше не парится, а просто другие знаки использовать для выделения вложенной части?
4
16 февраля 2008 года
mike
3.7K / / 01.10.2002
Думаю тут нужно делать без регулярных выражений - считать скобки.
420
17 февраля 2008 года
Fobos
197 / / 10.03.2006
Дело в том, что заранее не определено, сколько вложенных скобок будет. Т.е. может быть например:

{Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|} }
или
{Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|} Значение 4{тыры-пыры...}}
или
{Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|} Значение 4{тыры-пыры...} знач 5 {тыры-пыры..пырыры} знач n}

ну и т.д.

Вот я и бью голову целые 2 дня уже. :(
37K
08 марта 2008 года
Joker_V
1 / / 08.03.2008
Я в этом во всем еще начинающий, но я тебе уже смело могу сказать, что Майк на все сто процентов прав, по другому ты может и сделаешь, но мозги себе попаришь предельно сильно!
Можешь и с регулярным выражением, только скобки тебе все равно считать прейдется.
29K
12 марта 2008 года
ivtrans
19 / / 11.01.2008
Цитата: Fobos
Здравствуйте!
Встал довольно срочный вопрос. В общем никак немогу составить правильно регулярное выражение на 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

Подскажите, как мне быть.



preg_match("/{.*?}/", $stroka, $fVarsArray); вот так должны все скобки выбраться

92
12 марта 2008 года
Тень Пса
2.2K / / 19.10.2006
Цитата: ivtrans
preg_match("/{.*?}/", $stroka, $fVarsArray); вот так должны все скобки выбраться


[offtop]почему народ не читает то, что пишут выше? )[/offtop]

а вложенность за тебя сосед посчитает? ;)

2
12 марта 2008 года
squirL
5.6K / / 13.08.2003
данную задачу, навскидку, можно решить динамическими регулярками, но я не знаю, как оно работает в PHP и работает ли вообще
420
14 марта 2008 года
Fobos
197 / / 10.03.2006
Собстна уже понял как.
Вот как выделить главные от внутренних скобок:
Код:
$text = "Основ 1 {Знач 1{3.3|}{} {jhgjhgh} Знач 4{4.3|}ascasc} Основ 2 {Ещё{} кое-что}{Ещё{} кое-что} [] {} {{}}";
 $text2= $text;

    //Ищем пару скобке.
    for ($i=0; $i<=substr_count($text2, '}')-1; $i++)
    {
      $msoppos = strpos($text, '{');
      $msclpos = strpos($text, '}');//Находим позицию 1-й }
      //Если между откр (::main~ и найденым } количество откр. равно кол-ву закр. подскобок, то принимаем за главную и закрываем (заменяем на усл. знак.), если нет то дальше
      $buffer = substr($text, $msoppos+1, $msclpos-$msoppos-1);
      //Счит. кол-во { и }
      $socnt = substr_count($buffer, '{');
      $sccnt = substr_count($buffer, '}');
      $ssccnt = substr_count($buffer, '~sub::)');
     
      if ($socnt == $sccnt or $socnt == $ssccnt)//Если количество открывающих и закрывающих внутри равны, то значит наша закрывающая есть главная!!! УРА!!!
      {
        //Заменяем значения, чтобы к ним уже не возвращаться! Уффффф.
        $msoppos = strpos($text, '{');        
        $text = substr_replace($text, '(::main~', $msoppos, 1);//Заменяем { на (::main~
       
        $msclpos = strpos($text, '}');//Находим позицию 1-й }
        $text = substr_replace($text, '~main::)', $msclpos, 1);//Заменяем } на ~main::)
       
        //Теперь все внутренние закр. скобки заменяем на усл. знак. (::sub~
        $buffer2 = substr($text, $msoppos, $msclpos-$msoppos);
        $buffer3 = str_replace('{', '(::sub~', $buffer2);
        $text = str_replace($buffer2, $buffer3, $text);

      }
      else
      {
        $text = substr_replace($text, '~sub::)', $msclpos, 1);//Заменяем } на ~main::)
      }
    }

echo '<b>'.$text.'<br>';

Просто заменяет внешние скобки на (::main~ ~main::),
а внутренние на (::sub~ ~sub::).
А дальше уже просто с ними оперировать.
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Однако мой вариант не универсален и не позволяет учитывать неограниченную вложенность. Но мне по проекту в принципе того и не надо. :) Так, для интереса, было-б замечательно узнать.
353
14 марта 2008 года
Nixus
840 / / 04.01.2007
Не знаю как на php, но на perl это делается очень просто (если конечно правильно понял задачу :) ):

Код:
#!/usr/bin/perl

my $s = "Основное {Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|} Значение 4{Значение 4.1|Значение 4.2|Значение 4.3|} Значение 5} Основное 2";
recursivePrint(parse($s));

sub parse
{
    my $str = shift;
    my $cur = [];
    my @stack = ();
    my $tok = '';

    while($str =~ /(.)/sg)
    {
        my $c = $1;

        if($c !~ /^[{}\|]*$/) {
            $tok .= $c;
            next;
        }

        if($tok ne '') {
            push(@$cur, trim($tok));
            $tok = '';
        }

        if($c eq '{')
        {
            push(@stack, $cur);
            $cur = [];
        }
        elsif($c eq '}')
        {
            if(@stack) {
                my $a = pop(@stack);
                push(@$a, $cur);
                $cur = $a;
            } else {
                last;
            }
        }
    }

    ## Добавлено.
    while(@stack) {
        my $a = pop(@stack);
        push(@$a, $cur);
        $cur = $a;
    }

    return $cur;
}

sub trim
{
    my $s = shift;
    $s =~ s/^\s+|\s$//g;
    return $s;
}

sub recursivePrint
{
    local $level = 0;
    &_recursivePrint;
}

sub _recursivePrint
{
    my($arr) = @_;
    my $suff1 = "\t" x $level;
    $level++;
    my $suff2 = "\t" x $level;

    print $suff1, "{\n";

    foreach (@$arr)
    {
        if(ref $_ eq 'ARRAY') {
            _recursivePrint($_);
        } else {
            print $suff2, $_, "\n";
        }
    }

    print $suff1, "}\n";
    $level--;
}
9.0K
14 марта 2008 года
Toxin_F
93 / / 03.01.2007
посидел вот на досуге...
Код:
<?php
function str_exploding($str) {
//  $tt = gettimeofday();
//  $time = $tt['sec'] + $tt['usec'] / 1000000;
    $strpos = 0;
    $result = array();
    $i = 0;
    while (!empty($str[$strpos])) {
        if ($str[$strpos] == '{' or $str[$strpos] == '}') {
            $result[$i] = trim($result[$i]);
            $i++;
            $strpos++;
            $result[$i] = '';
        }
        $result[$i] .= $str[$strpos];
        $strpos++;
    }
//  $tt = gettimeofday();
//  $time = ($tt['sec'] + $tt['usec'] / 1000000) - $time;
//  $result['time'] = 'Длительность действия: '.sprintf('%.5f', $time);
    return $result;
}
$str = 'Основное {Значение 1|Значение 2|Значение 3 {Значение 3.1|Значение 3.2|Значение 3.3|} Значение 4{Значение 4.1|Значение 4.2|Значение 4.3|} Значение 5} Основное 2';
$prs = str_exploding($str);
foreach ($prs as $line) {
    echo '- '.$line.'<br />';
}
?>
Результат:
- Основное
- Значение 1|Значение 2|Значение 3
- Значение 3.1|Значение 3.2|Значение 3.3|
- Значение 4
- Значение 4.1|Значение 4.2|Значение 4.3|
- Значение 5
- Основное 2
353
14 марта 2008 года
Nixus
840 / / 04.01.2007
Можно в разы короче :) :

 
Код:
function str_exploding($str) {
    return preg_split('/\s*[{}]\s*/', trim($str));
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог