2

順序付きリストをフォーマットするマークアップを作成しようとしています。マークアップ スタイルは次のとおりです。

$strings = "1. dog
1. cat
1. fish
 1. horse
 1. monkey
1. pig
";

horse番号の前に1つのスペースがあるため、monkeyそのリストからサブリストの一部にする必要があります。私が使用しているコードは次のとおりです。

function blq($match){
    $str = preg_replace("/^1\. (.+?)$/m", "<li>$1</li>", $match[0]);
    $str = preg_replace_callback("/(?:^1\. .+(\n|$))+/m", 'blq', $str);
    return "<ol>$str</ol>";
}

$string = preg_replace_callback("/(?:^ ?1\. .+(\n|$))+/m", 'blq', $strings);

echo $string;

そのコードはこの出力を作成しています:

<ol><li>dog
</li>
<li>cat
</li>
<li>fish
</li>
 1. horse
 1. monkey
<li>pig
</li>
</ol>

horseサブリストとして作成さmonkeyれず、単に無視されました。答えに近づいた気がしますが、その答えにたどり着くにはどうすればよいかわかりません...

無制限の数のサブリストを許可したいことに注意してください

4

1 に答える 1

2
<?php

$text = "1. dog
1. cat
1. fish
 1. horse
  1. duck
   1. goose
  1. swan
 1. monkey
  1. chimpanzee
  1. orangutan
  1. whale
1. pig
";

function callback($match) {
    $out = preg_replace_callback("/(^($match[2] +)1\. .+(\\n|$))(?1)*/m", 'callback', $match[0]);
    $out = preg_replace("/^$match[2]1\. (.+)$/m", "<li>$1</li>", $out);
    return "<ol>\n$out</ol>\n";
}

$html = preg_replace_callback("/(^( *)1\. .+(\\n|$))(?1)*/m", 'callback', $text);

echo $html;

?>

ここにイデオンのデモがあります。


preg_replace_callback再帰的に使用することは、あなたが持っていた非常に素晴らしいアイデアです。また、$-strings がセット変数でない限り、二重引用符内で補間されないことについては正しいです。私はいつもそれを忘れています。そして、各行の先頭 (文字列全体の先頭ではなく) に一致させ/mたいので使用するのは正しかったし、それがモードの各行の末尾に一致するにもかかわらず、使用するのも正しかった。を実際に消費しないため、動作しません。あなたの質問を最初に読んだとき、私はこれらの事実を見ませんでした。^(\n|$)$/m+$\n

それでは、最初の式から始めましょう。

/(^( *)1\. .+(\\n|$))(?1)*/m

実際には、再帰部分式 ,(?1)は速記の場合を除いて必要ありません。それを拡張しましょう:

/(^( *)1\. .+(\\n|$))(^( *)1\. .+(\\n|$))*/m
 |                  ||                  |
 +------------------++------------------+

したがって、2 つの同一の半分があります。あなたがしたように使わないのはなぜ+ですか?最初の行をインデントするスペースの数だけをキャプチャしたいからです。これらのスペースは に格納され$match[2]ます。

コールバック内で、これらのスペースに加えて、1 つ以上のスペースを戻します。

/(^($match[2] +)1\. .+(\\n|$))(?1)*/m

そうすれば、再帰の各レベルで、現在のインデント レベル (より多くのスペース)よりのレベルのみを調べます。そして、再帰が巻き戻されると、正確にそのレベルの数のスペースでインデントされた行のみが、でラップされます。preg_replace_callback$match[2]<li></li>

/^$match[2]1\. (.+)$/m

に包まれた全体を返す前に<ol></ol>

于 2013-10-15T19:19:44.757 に答える