php - preg_replace 和 preg_match_all 之间的不同结果

标签 php regex preg-replace preg-match-all

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

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

我使用这一行来选取主题标签,以便在用户发布消息时将它们存储在单独的字段中,这会选取除新行开头的主题标签之外的所有主题标签。

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

使用 ms 修饰符没有任何区别。第二次我做错了什么?

编辑:输入文本可以是纯文本或 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将填充所有匹配的标签.

See it working

关于php - preg_replace 和 preg_match_all 之间的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12236224/

相关文章:

php - date() 返回错误的日期,尽管时间戳是正确的!

php - Moodle 网络服务 Rest api,发送加密邮件

php - 基于 MySQL 结果在 PHP while 循环内每第一次和第四次运行脚本

javascript - 用返回函数替换PHP中的字符串

python - 为什么我的正则表达式模式允许数字?

php - 使用 preg_replace 清理小部件输出 HTML

JavaScript 正则表达式 : blacklist 5 chars

javascript - 匹配不包含某个子串的子串

php - 除了带有远程链接的 anchor 之外,我如何去除标签?

php - 正则表达式删除除表情符号以外的所有非字母数字字符