我有一个支持主题标签的论坛。我正在使用以下行将所有主题标签转换为链接。我正在使用(^|\(|\s|>)
模式来避免在URL中选择命名锚点。
$str=preg_replace("/(^|\(|\s|>)(#(\w+))/","$1<a href=\"/smalltalk.php?Tag=$3&".SID."\">$2</a>",$str);
我正在使用这一行来获取主题标签,以便在用户发布消息时将它们存储在一个单独的字段中,这将获取除新行开头之外的所有主题标签。
preg_match_all("/(^|\(|\s|>)(#(\w+))/",$Content,$Matches);
使用m
&amp; s
修饰符没有任何区别。我在第二次做错了什么?
编辑:输入文本可以是纯文本或HTML。问题输入示例:
#startoftextreplacesandmatches #afterwhitespacereplacesandmatches <b>#insidehtmltagreplacesandmatches</b> :)
#startofnewlinereplacesbutdoesnotmatch :(
答案 0 :(得分: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])).'&'.SID.'">#'.htmlspecialchars($matches[2]).'</a>';
}
}, $str);
运行上述代码后,$str
将包含已修改的字符串,已正确转义以进行直接输出,$hashtags
将填充所有匹配的代码。