Применить PHP regex replace к многоканальному шаблону - PullRequest
2 голосов
/ 01 мая 2010

Допустим, у меня есть этот ввод:

I can haz a listz0rs!
# 42
# 126
I can haz another list plox?
# Hello, world!
# Welcome!

Я хочу разделить его так, чтобы каждый набор строк, начинающих с хеша, стал списком:

I can haz a listz0rs!
<ul>
    <li>42</li>
    <li>126</li>
</ul>
I can haz another list plox?
<ul>
    <li>Hello, world!</li>
    <li>Welcome!</li>
</ul>

Если я запускаюввод против регулярного выражения "/ (?: (?: (? <= ^ #) (. *) $) +) / m", я получаю следующий результат: </p>

Array
(
    [0] => Array
    (
        [0] => 42
    )
    [1] => Array
    (
        [0] => 126
    )
    [2] => Array
    (
        [0] => Hello, world!
    )
    [3] => Array
    (
        [0] => Welcome!
    )
)

Это нормально иДенди, но он не различает два разных списка.Мне нужен способ заставить квантификатор возвращать объединенную строку всех вхождений или, в идеале, массив всех вхождений.

В идеале это должен быть мой вывод:

Array
(
    [0] => Array
    (
        [0] => 42
        [1] => 126
    )
    [1] => Array
    (
        [0] => Hello, world!
        [1] => Welcome!
    )
)

Есть ли способ достичь этого, и если нет, есть ли близкая альтернатива?

Ответы [ 6 ]

1 голос
/ 02 мая 2010

Если вы хотите сделать это с регулярными выражениями, вам понадобится два. Используйте регулярное выражение ^(#.*\r?\n)+ для сопоставления каждого списка и добавления тегов вокруг него. В каждом списке (в соответствии с первым регулярным выражением) выполните поиск и замену ^#.* на <li>$0</li>, чтобы добавить теги вокруг каждого элемента списка. Для обоих регулярных выражений требуется ^ для сопоставления при переносе строки (флаг /m в PHP).

В PHP вы можете использовать preg_replace_callback и preg_replace для достижения этого всего за несколько строк кода.

$result = preg_replace_callback('/^(#.*\r?\n)+/m', 'replacelist', $subject);

function replacelist($groups) {
  return "<ul>\n" .
    preg_replace('/^#.*/m', '    <li>$0</li>', $groups[0])
    . "</ul>\n";
}
0 голосов
/ 01 мая 2010

С таким структурированным контентом я бы не стал использовать это как регулярное выражение. Как насчет другого подхода?

$your_text = <<<END
I can haz a listz0rs!
# 42
# 126
I can haz another list plox?
# Hello, world!
# Welcome!
END;

function printUnorderedList($temp) {
    if (count($temp)>0) {
        print "<ul>\n\t<li>" .implode("</li>\n\t<li>", $temp) . "</li>\n</ul>\n";
    }
}

$lines = explode("\n", $your_text);
$temp = array();
foreach($lines as $line) {
    if (substr($line, 0, 1) == '#') {
        $temp[] = trim(substr($line,1));
    } else {
        printUnorderedList($temp);
        $temp = array();
        echo $line . "\n";
    }
}
printUnorderedList($temp);
0 голосов
/ 01 мая 2010

похоже синтаксическая ошибка уже объяснил, что я делаю. Но здесь идет ссылка на рабочий пример .

0 голосов
/ 01 мая 2010

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

// You can get this by using file('filename') or 
// just doing an explode("\n", $input)
$lines = array(
    'I can haz a listz0rs!',
    '# 42',
    '# 126',
    'I can haz another list plox?',
    '# Hello, world!',
    '# Welcome!'
);

$hashline = false;
$lists = array();
$curlist = array();
foreach ($lines as $line) {
    if ($line[0] == '#')
        $curlist[] = $line;
    elseif ($hashline) {
        $lists[] = $curlist;
        $curlist = array();
        $hashline = false;
    }
}

Небольшая очистка может быть в порядке, но, надеюсь, это поможет.

(после прочтения новых ответов это, в основном, глубокое объяснение ответа синтаксической ошибки.)

РЕДАКТИРОВАТЬ: Вы также можете убрать # в начале каждой строки.

0 голосов
/ 01 мая 2010

Если бы это был я, я бы:

  1. взорваться ("\ n", $ input) в массив, где 1 ключ = строка
  2. foreach через этот массив
  3. всякий раз, когда вы получаете строку, которая не начинается с #, тогда вы добавляете закрывающие / открывающие теги ul

Добавьте еще немного, чтобы справиться с неожиданным вводом (например, две строки без хеша подряд), и все в порядке.

0 голосов
/ 01 мая 2010

Я бы сказал, что не пытайтесь делать все это в одном регулярном выражении - вместо этого сначала используйте регулярное выражение, чтобы сопоставить наборы последовательных строк, начинающихся со знаков #, и оберните эти строки парой <ul></ul> , Затем используйте второе регулярное выражение (или даже не регулярное выражение вообще - вы можете просто разбить на разрывы строк), чтобы сопоставить каждую отдельную строку и преобразовать ее в формат <li></li>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...