PHP regex bir multi-line tekrarlanan deseni yerine uygulayın

6 Cevap php

Diyelim ki bu girişi var diyelim:

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

Ben karma-başladım hatlarının her set bir liste olur böylece bölmek istiyorum:

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>

Ben regex karşı girişi çalıştırırsanız "/ (:? (:? (<= ^ #) (*) $) +?). / M", ben şu sonucu alırsınız:

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

Bu ince ve züppe, ama farklı iki liste arasında ayrım yapmaz. Ben, ideal, tüm olaylar bir dizi nicelik tüm olaylar bir zincirleme dize döndürür yapmak, ya da bir yol gerekir.

İdeal olarak, bu benim çıkış olmalıdır:

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

Bunu sağlamanın bir yolu var mı, yok ise, yakın bir alternatif var mı?

6 Cevap

Düzenli ifadeler ile bunu yapmak istiyorsanız, iki gerekir. Regex kullanın ^(#.*\r?\n)+ her liste maç ve çevresinde etiketleri eklemek için. Her bir liste içinde (ilk regex ile eşleşti gibi), ^#.* <li>$0</li> Her liste öğesi etrafında etiketleri eklemek ile arama ve değiştirme. Her iki regexes gerektiren ^ satır sonları at (PHP /m bayrak) eşleşecek.

PHP Eğer preg_replace_callback kullanabilir ve preg_replace kod sadece birkaç satır bunu başarmak için.

$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";
}

Bunun yerine, her şeyden önce # işaretleri ile başlar ardışık satır setleri maç ve bir {[(bu satırların sarmak için bir düzenli ifade kullanın - Ben bir tek regex hepsini yapmaya kalkmayın derim 1)]} çifti. Sonra ikinci bir regex kullanmak (veya hiç hatta bir regex - sadece satır sonlarını bölünmüş olabilir) her satırı maç ve <li></li> biçimine dönüştürmek için.

Benim olsaydı yapardım:

  1. Bir dizi 1 tuşu = satır içine ("\ n", $ girdi) patlayabilir
  2. Bu dizi sayesinde foreach
  3. Bir # ile başlamıyor bir hat almak zaman, o ul etiketleri açılış / kapanış sizin eklediğinizde bulunuyor

(Arka arkaya iki sigara karma hatları gibi) beklenmedik girişi ile başa çıkmak için biraz daha ekleyin ve iyisin.

Syntax Error zaten ben ne yapıyorum açıklamıştır gibi görünüyor. Ama burada bir working example bağlantısını gider.

Bu gibi yapılandırılmış içerik ile, bir regex olarak bunu yapmaz. Nasıl başka bir yaklaşım hakkında?

$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);

Sen tamamen regex önlemek, ve sadece o hat ile dosya, satır (satır bir dizi) okunabilir ve olmayan bir karma-üyeye hattını karşılaşır her zaman, yeni bir listesini başlatır alarak basit bir yaklaşım deneyebilirsiniz. Şöyle:

// 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;
    }
}

Biraz temiz-up amacıyla olabilir, ama umarım yardımcı olur.

(Yeni cevapları okuduktan sonra, bu temelde sözdizimi hatası cevabı bir derinlemesine açıklama.)

EDIT: Bunu da her satırın başında # kapalı şerit isteyebilirsiniz.