检测给定字符串周围的字符是否均匀匹配

时间:2014-06-18 07:53:11

标签: php regex string markdown

我正在构建一个包含伪标记的脚本。

  • 用星号(*)包裹字符串会使文字变为粗体,方法是将字符替换为<strong>string</strong>
  • 用克拉(^)包裹一个字符串会强调文字,方法是用<em>string</em>
  • 替换字符

我正在使用以下正则表达式路径来评估它:

$src    = preg_replace('/\*([^*]*)\*/', "<strong>$1</strong>", $inputText);
$in     = preg_replace('/\^([^^]*)\^/', "<em>$1</em>", $src);
$output = rtrim(preg_replace("/(^[\n\n]*|^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $in), "\r\n");

执行以下任务:

  • 使用<strong>标记
  • 替换星号
  • <em>标签
  • 替换克拉
  • 剥去空白行,并取出尾随换行符

我的问题

在我的验证中,我想防止发生错位的降价。如果用户输入:*^this is test^*,则可以正常使用。但如果他们(无意中)*^this is test*^输入,则会产生HTML <strong><em>this is test</strong></em>,这当然是无效的标记。

我想在我的验证方法中阻止这种情况,但我不确定如何以检查适当匹配对的方式解析它。我怎么能做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以这样继续:

$data = ' markdown. If a user enters: *^this is test^*, it will work fine. But
         if they enter (inadvertently) *^this is test*^, it will';

$pattern = '~([*^])((?>[^^*]+|(?R))+)\1~';

$corr = array('*' => 'strong', '^' => 'em');

do {
    $data = preg_replace_callback($pattern, function($m) use ($corr) {
        return '<' . $corr[$m[1]] . '>' . $m[2] . '</' . $corr[$m[1]] . '>'; 
    }, $data, -1, $count);
} while ($count > 0);

echo htmlspecialchars($data);

注意:如果您想允许空字符串(即+*),则可以将最后一个量词从<em></em>更改为<strong></strong>

使用堆栈的另一种方式:

$stack = array();
$arr = preg_split('~([*^])~', $data, -1, PREG_SPLIT_DELIM_CAPTURE);

for ($k = 1; $k<count($arr); $k+=2) {
    $lval = end($stack);
    $lkey = key($stack);
    if ($lval == $arr[$k]) {
        $arr[$lkey] = '<' . $corr[$lval] . '>';
        $arr[$k] = '</' . $corr[$lval] . '>';
        array_pop($stack); 
    } else {
        $stack[$k]=$arr[$k];
    }
}

$result = implode('',$arr);    

答案 1 :(得分:1)

要防止这些匹配嵌套代码的情况,请将正则表达式更改为:

$src    = preg_replace('/\*([^^*]*)\*/', "<strong>$1</strong>", $inputText);
$in     = preg_replace('/\^([^^*]*)\^/', "<em>$1</em>", $src);