Мне очень интересно работать над этим Regex. У меня есть список строки, содержащей несколько строк. Допустим

$ingredients = '--For Salad ~20 mins~
1 1/2 Cup warm water (105°F-115°F)
2 1/4 Teaspoon active dry yeast
1 Cup packed dark brown sugar
2 tbsp Finely chopped garlic
1 tbsp Tabasco
--For Marination ~35 mins~
3 tbsp Fresh lime juice
1 tbsp Fresh orange juice
1 tbsp Dijon mustard
1 tsp Curry powder, toasted
1/2 teaspoon salt
1/4 teaspoon black pepper
1/2 cup olive oil ';

$list = explode("\n", $ingredients);

foreach ($list as $key => $data)
{
    $data = preg_replace('/^\s*\-{2}(.*)/', '<h4>$1</h4>', $data);
    $pos = strpos($data, '<h4>');
    if ($pos === false)
    {
        echo '<span class="name">' . $data . '</span>';
    } else
    {
        echo $data;
    }
}

Как мне сопоставить другой шаблон и заменить его другими элементами и добавить внутри другой строки замены.

В первой строке строка, начинающаяся с двойных дефисов, содержит параметр, начинающийся и заканчивающийся Tilde ~.

Я хочу получить другие шаблоны для каждой строки и вывести их.

Вывод я хочу посмотреть как ниже.

<h4>For Salad  <span class="duration">20 mins</span></h4>
<span class="name">1 1/2 Cup warm water (105°F-115°F)</span>
<span class="name">2 1/4 Teaspoon active dry yeast</span>
<span class="name">1 Cup packed dark brown sugar</span>
<span class="name">2 tbsp Ffinely chopped garlic</span>
<span class="name">1 tbsp Tabasco</span>
<h4>For Marination <span class="duration">35 mins</span></h4>
<span class="name">3 tbsp Fresh lime juice</span>
<span class="name">1 tbsp Fresh orange juice</span>
<span class="name">1 tbsp Dijon mustard</span>
<span class="name">1 tsp Curry powder, toasted</span>
<span class="name">1/2 teaspoon salt</span>
<span class="name">1/4 teaspoon black pepper</span>
<span class="name">1/2 cup olive oil </span>

Другой вывод, который я пытаюсь получить, это получить этот h4 отдельно от других шаблонов.

<h4>For Salad</h4><span class="duration">20 mins</span>
1
Maqk 2 Май 2017 в 14:26

3 ответа

Лучший ответ

Надеюсь, это поможет вам. Здесь мы ищем ~ и заменяем ~([^~]+)~ тегами span вокруг него.

1. ~([^~]+)~ это будет соответствовать всем символам между ~, включая ~

Попробуйте этот фрагмент кода здесь

<?php

ini_set('display_errors', 1);

$ingredients = '--For Salad ~20 mins~
1 1/2 Cup warm water (105°F-115°F)
2 1/4 Teaspoon active dry yeast
1 Cup packed dark brown sugar
2 tbsp Ffinely chopped garlic
1 tbsp Tabasco
--For Marination ~35 mins~
3 tbsp Fresh lime juice
1 tbsp Fresh orange juice
1 tbsp Dijon mustard
1 tsp Curry powder, toasted
1/2 teaspoon salt
1/4 teaspoon black pepper
1/2 cup olive oil ';

$list = explode("\n", $ingredients);

foreach ($list as $key => $data)
{
    $data = preg_replace('/^\s*\-{2}(.*)/', '<h4>$1</h4>', $data);
    $pos = strpos($data, '~');
    if ($pos !== false)
    {
        echo $data = preg_replace("/~([^~]+)~/", '<span class="duration">$1</span>', $data);
    } 
    else
    {
        //replacing data with span tags around it
        echo $data = str_replace($data, '<span class="name">'.$data.'</span>', $data);
    }
    echo PHP_EOL;
}

Решение 2: (another format) Попробуйте этот фрагмент кода здесь

foreach ($list as $key => $data)
{
    if (preg_match('/^\s*\-{2}([^~]+)(~[^~]+~)/', $data,$matches) && strpos($data, '~') !== false)
    {
        echo "<h4>".$matches[1]."</h4>";
        echo '<span class="duration">'.$matches[2].'</span>';
    } 
    else
    {
        //replacing data with span tags around it
        echo $data = str_replace($data, '<span class="name">'.$data.'</span>', $data);
    }
    echo PHP_EOL;
}
1
Sahil Gulati 2 Май 2017 в 14:00

Попробуйте решить, что делать с каждой строкой, прежде чем что-либо заменить:

foreach ($list as $key => $data)
{
    $matches = [];
    if (preg_match('/^--(.*)~(.*)~$/', $data, $matches) {
        echo '<h4>' . $matches[1] . '</h4>' .
             '<span class="duration">' . $matches[2] . '</span>';
    } else {
        echo '<span class="name">' . $data . '</span>';
    }
}
1
Pharaoh 2 Май 2017 в 11:38

Я сделаю это за один выстрел с preg_replace_callback без взрыва:

$display = preg_replace_callback('/^\h*(?:--([^\n~]+)~([^\n~]+)~|([^\r\n]+))/m', function ($m) {
    return isset($m[3]) ? '<span class="name">' . $m[3] . '</span>'
                        : '<h4>' . $m[1] . '<span class="duration">' . $m[2] . '</span></h4>';
}, $ingredients);

echo $display;

демонстрация

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

2
Casimir et Hippolyte 2 Май 2017 в 11:53