2

我有一个支持主题标签的论坛。我正在使用以下行将所有主题标签转换为链接。我正在使用该(^|\(|\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);

使用m&s修饰符没有任何区别。在第二种情况下我做错了什么?

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

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

1 回答 1

2

您的替换操作有一个您显然还没有遇到过的问题——它将允许未转义的 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填充所有匹配的标签。

看到它工作

于 2012-09-02T15:14:46.897 回答