PHP preg_split, если не внутри фигурных скобок - PullRequest
2 голосов
/ 29 августа 2009

Я создаю интерпретатор языка сценариев, использующий PHP. У меня есть этот код на этом языке сценариев:

write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly

(Да, в это трудно поверить, но это синтаксис)

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

  1. запись
  2. Привет, мир!
  3. в
  4. либо
  5. The
  6. цвет
  7. синий
  8. или
  9. красный
  10. или
  11. # 00AA00
  12. и
  13. в
  14. либо
  15. The
  16. шрифт
  17. Arial Black
  18. или
  19. Монако
  20. , где
  21. и
  22. The
  23. цвет
  24. и
  25. шрифт
  26. есть
  27. определяется
  28. случайно

(строки внутри фигурных скобок показаны выше жирным шрифтом ) Строки внутри фигурных скобок должны состоять из одного элемента. Так что {Hello, World!} Не может быть: 1. Привет, 2. Мир!

Как я могу это сделать?

Заранее спасибо.

Ответы [ 5 ]

5 голосов
/ 29 августа 2009

как насчет использования что-то вроде этого:

$str = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';

$matches = array();
preg_match_all('#\{.*?\}|[^ ]+#', $str, $matches);

var_dump($matches[0]);

Что вам даст:

array
  0 => string 'write' (length=5)
  1 => string '{Hello, World!}' (length=15)
  2 => string 'in' (length=2)
  3 => string 'either' (length=6)
  4 => string 'the' (length=3)
  5 => string 'color' (length=5)
  6 => string '{blue}' (length=6)
  7 => string 'or' (length=2)
  8 => string '{red}' (length=5)
  9 => string 'or' (length=2)
  10 => string '{#00AA00}' (length=9)
  11 => string 'and' (length=3)
  12 => string 'in' (length=2)
  13 => string 'either' (length=6)
  14 => string 'the' (length=3)
  15 => string 'font' (length=4)
  16 => string '{Arial Black}' (length=13)
  17 => string 'or' (length=2)
  18 => string '{Monaco}' (length=8)
  19 => string 'where' (length=5)
  20 => string 'both' (length=4)
  21 => string 'the' (length=3)
  22 => string 'color' (length=5)
  23 => string 'and' (length=3)
  24 => string 'the' (length=3)
  25 => string 'font' (length=4)
  26 => string 'are' (length=3)
  27 => string 'determined' (length=10)
  28 => string 'randomly' (length=8)

Вам просто нужно перебрать эти результаты; те, которые начинаются с {и заканчиваются}, будут вашими "важными" словами, а остальные - остальными.


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

foreach ($matches[0] as $word) {
    $m = array();
    if (preg_match('#^\{(.*)\}$#', $word, $m)) {
        echo '<strong>' . htmlspecialchars($m[1]) . '</strong>';
    } else {
        echo htmlspecialchars($word);
    }
    echo '<br />';
}

Или, как вы сказали, работа с strpos и strlen тоже сработает; -)

0 голосов
/ 21 декабря 2018

Вы хотите разбить все пробелы, которые не содержатся в фигурных скобках.

Сопоставьте фигурные выражения или последовательность непробельных символов, затем проигнорируйте эти совпадения с \K, затем используйте следующий пробел в качестве разделителя.

Код: ( Демо )

$text = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';

var_export(preg_split('~({[^}]*}|\S+)\K ~', $text));

p.s. Вы можете заменить фигурные скобки на сильные теги, например: https://3v4l.org/fXrgE

p.p.s. Вы можете создать свой точный упорядоченный список с помощью preg_replace_callback(): ( Demo ) <- перейдите на phptester.net, чтобы увидеть, как он отображается </p>

$text = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';

echo "<ol>" , preg_replace_callback('~{([^}]*)}|(\S+)~', function($m) {
        if (!isset($m[2])) {
            return "<li><strong>{$m[1]}</strong></li>\n";
        }
        return "<li>{$m[2]}</li>\n";
    },
    $text) , "<ol>";
0 голосов
/ 29 августа 2009

Это можно сделать итеративно, без регулярных выражений. Вы перебираете всю строку. Вы помещаете каждый символ во временную переменную, если не найдете пробел. Когда вы найдете пробел, вы помещаете содержимое временной переменной в массив, очищаете его и затем продолжаете.

Если вы найдете скобку, вы устанавливаете логическое значение, а затем помещаете все в временную переменную, пока не найдете закрывающую скобку. И так далее.

<?php
$string = "write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly";
$bracket = false;
$words = array();
$temp = "";

for($i = 0; $i < strlen($string); $i++){    
    $char = $string[$i]
    if($bracket){
        $temp .= $char;
        if($char == "}"){
            $bracket = false;
            $words[] = $temp;
        }
    }
    else{
        if($char == " "){
            if($temp != ""){
                $words[] = $temp;
                $temp = "";
            }
        }
        elseif($char == "{"}{
            $temp .= $char;
            $bracket = true;
        }
        else{
            $temp .= $char;
        }
    }
}
?>

Код не проверен.

0 голосов
/ 29 августа 2009

Я бы заменил их, используя preg_replace_callback . С помощью функции обратного вызова вы можете отслеживать порядок и заменять их на что-то вроде% var1%,% var2% и т. Д.

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

0 голосов
/ 29 августа 2009

Имеет ли значение заказ? Если нет, вы можете извлечь все {}, удалить их, а затем обработать оставшуюся строку.

...