Different results between preg_replace & preg_match_all


Different results between preg_replace & preg_match_all

我有一个支持标签的论坛。我使用以下行将所有标签转换为链接。我使用(^|'(|'s|>)模式来避免在URL中拾取命名锚。

$str=preg_replace("/(^|'(|'s|>)(#('w+))/","$1<a href='"/smalltalk.php?Tag=$3&amp;".SID."'">$2</a>",$str);

当用户发布消息时,我用这一行来提取标签并将其存储在一个单独的字段中,这会提取除新行开头的标签之外的所有标签。

preg_match_all("/(^|'(|'s|>)(#('w+))/",$Content,$Matches);

使用CCD_ 2&s修饰语没有任何区别。我在二审中做错了什么?

编辑:输入文本可以是纯文本或HTML。问题输入示例:

#startoftextreplacesandmatches #afterwhitespacereplacesandmatches <b>#insidehtmltagreplacesandmatches</b> :)
#startofnewlinereplacesbutdoesnotmatch :(

您的替换操作有一个问题,您显然还没有遇到这个问题——它将允许无标题的HTML特殊字符通过。我之所以知道这一点,是因为正则表达式允许在标签前面加上>,这是一个特殊字符。

因此,我建议您使用此代码进行替换,它将兼作提取要插入数据库的标签的代码:

$hashtags = array();
$expr = '/(?:(?:(^|[(>'s])#('w+))|(?P<notag>.+?))/';
$str = preg_replace_callback($expr, function($matches) use (&$hashtags) {
    if (!empty($matches['notag'])) {
        // This takes care of HTML special characters outside hashtags
        return htmlspecialchars($matches['notag']);
    } else {
        // Handle hashtags
        $hashtags[] = $matches[2];
        return htmlspecialchars($matches[1]).'<a href="/smalltalk.php?Tag='.htmlspecialchars(urlencode($matches[2])).'&amp;'.SID.'">#'.htmlspecialchars($matches[2]).'</a>';
    }
}, $str);

运行上述代码后,$str将包含修改后的字符串,并正确转义以直接输出,$hashtags将填充所有匹配的标记。

查看它的工作