【问题标题】:Regex to create html from custom code正则表达式从自定义代码创建 html
【发布时间】:2012-10-30 15:49:52
【问题描述】:

我有一个文本字段,用户可以在其中编写特定命令来获取一些 html。

例如:

Text Text Text Text

[*] first entry
[*] second entry
[*] 3rd...

Text Text

这个文本应该用正则表达式转换成这样的:

text text

<ol>
 <li>FirstEntry</li>
 <li>Second</li>
 ..
</ol>

text text

有什么建议吗?

与条目匹配的正则表达式是这样的:

/\[\*\].+/i

问题是如何正确插入&lt;ol&gt;&lt;/ol&gt;

我的解决方案

我在想我可以解析所有文本行,当解析器遇到以 [*] 开头的第一行时,然后输入 &lt;ol&gt; &lt;/ol&gt; 同样的事情

到目前为止,我已经制作了将单个 [*] ... 转换为 &lt;li&gt; ... 的脚本

http://codepad.org/yzRVupON

preg_replace('/\[\*\](.+)/i','<li>$1</li>',$str);

我需要&lt;ol&gt; 部分

我的实现

http://codepad.org/NNgC6uko

【问题讨论】:

  • 你想看看phps正则表达式函数preg_replace_callback()
  • 感谢您的输入.. 但我知道该功能,但我不知道如何使用它
  • 为什么,您使用正则表达式来匹配模式[*] first entry 等等,并且对于每个这样的匹配,您实现的回调函数都会被调用。在该函数中,您可以输出任何您想要的标记,例如&lt;li&gt;FirstEntry&lt;/li&gt;
  • 这不是问题:)。问题更像是如何正确插入
  • 好吧,也许通过使用另一个正则表达式模式来做同样的事情?虽然这更容易,但您不需要回调,但可以使用普通的 preg_replace() 函数。

标签: php html regex


【解决方案1】:

为什么不使用 preg_replace 将标签放在两边? 可能像下面这样。

$string = <<<EOF
Text Text Text Text

[*] first entry
[*] second entry
[*] 3rd...

Text Text
EOF;

$pattern = '/(\[\*\])([\d\D]+)(\[\*\].*)/';
$replacement = '<ol> ${1}${2}${3} </ol>';
$string = preg_replace($pattern, $replacement, $string);

$pattern = '/\[\*\](.+)/i';
$replacement = '<li>${1}</li>';

echo  preg_replace($pattern, $replacement, $string);

输出:

Text Text Text Text

    <ol>
        <li> first entry </li>
        <li> second entry </li>
        <li> tag 3rd... </li>
    </ol>

Text Text

【讨论】:

  • @m.buettner 哦。将寻找更酷的正则表达式。感谢您指出这一点。
  • 检查我的答案...我做了一个小脚本
  • @yes123 酷。我仍然会尝试编写纯粹的preg_match 解决方案。 (为了好玩);)
  • @yes123 的脚本要好得多,但可以轻松扩展为更通用的解决方案。我同意。
【解决方案2】:

这是我的实现。工作代码:http://codepad.org/NNgC6uko

这个脚本很容易定制,可以从命令到 HTML 的任何类型的翻译

function parseText($txt) {

    $lines = preg_split('/[\r\n]+/',$txt,null,PREG_SPLIT_NO_EMPTY);
    $newLines = array();

    $lastTag = '';
    foreach($lines as $k=>$v) {

        $currentTag = $v[0];

        //$newLine = $v;
        $newLine = preg_replace('/^\* (.+)$/','<li>$1</li>',$v);

        if ($currentTag=='*' && $lastTag != '*')
            $newLines[] = '<ol>';

        else if ( $lastTag == '*' && $currentTag != '*' )
            $newLines[] = '</ol>';  

        $newLines[] = $newLine;



        $lastTag = $currentTag;

    }

    print_r($newLines);
}

【讨论】:

  • 这看起来不错,但使用 explode() 而不是 preg_split 来获取新行。对于较大的字符串,它应该更快。正则表达式是一个很棒的工具,但使用起来更昂贵。 stackoverflow.com/questions/1483497/…。例如。 $lines = explode("\n", $txt);
  • \n 仅适用于 linux... windows 使用 \r\n... 也使用 explode 多行将被分开.. \n\n\n
【解决方案3】:

用正则表达式进行这种解析可能不是可行的方法;对于非常简单的场景可能还可以,但是您尝试添加的功能越多,它就越难——直到它变得无法维护。

我建议从例如借用解析技术。各种 MarkDown 解析器;请参阅thesequestions 了解更多信息(还有其他信息)。

回到原来的问题:如果你被限制只能使用正则表达式,你可以尝试首先将整个“列表块”与类似的东西匹配

/^(\s*\[\*\].*?$)+/m

(多行模式modifier必不可少)

然后,您可以使用当前的正则表达式将匹配的文本分解为单独的列表项,然后用 &lt;ol&gt;&lt;/ol&gt; 包围结果来生成输出。

【讨论】:

  • 如果我将每一行放入一个数组中会怎样...然后我解析整个数组,当我看到第一行以 [*] 开头时,我插入一个 &lt;ol&gt; ?跨度>
  • 这是一个非常简单的解析器的描述,所以这是朝着正确方向迈出的一步。但是首先检查现有代码,如果您可以修改已经测试过的东西,那么编写自己的代码是没有意义的。
  • 这就是重新发明轮子的问题。但我不需要 Markdown 或其他解析器的所有功能......
猜你喜欢
  • 1970-01-01
  • 2010-10-01
  • 2012-07-26
  • 1970-01-01
  • 2015-08-20
  • 2012-05-23
  • 1970-01-01
  • 2020-12-29
  • 1970-01-01
相关资源
最近更新 更多