PHP 中的多字节正则表达式和主题标签解析

Multibyte regex and hashtag parsing in PHP

我目前正在开展一个项目,用户可以在该项目中使用文本区域中的主题标签来标记他们的内容。保存 post 时,我浏览内容以找到任何主题标签,保存它们并将它们与 post 模型相关联。除了一个缺陷外,一切正常,没有多字节支持,这是一个错误问题,因为这个项目将是国际化的,并且具有广泛的语言支持。

例如,假设我的 post:

中有此内容
$content = 'This is my testing string, look at the hashtags and see that the multibyte ones are ignored. #php #regex #my #multibyte #åäö #öl #läsa #drickaöl #tags #are #being #ignored'

我目前正在使用 preg_match_all 获取所有主题标签,如下所示:

preg_match_all('/(#\w+)/', $content, $matches);

尽管如此,这将忽略任何以多字节符号开头的标签,例如 å、ä 或 ö,或者简单地在每个遇到标签的地方中断每个标签。

人们一直在推荐 mb_ereg() 方法,但据我所知,它只支持获取布尔结果,指示您的字符串是否与模式匹配。

你可以看看我的简单正则表达式 here

请帮助我理解并可能修复此问题,以便我可以使此功能正常工作。

非常感谢!

您需要在正则表达式中使用 u 标志:

$re = '/#\w+/u';

IDEONE demo

$re = '/#\w+/u'; 
$str = "This is my testing string, look at the hashtags and see that the multibyte ones are ignored. #php #regex #my #multibyte #åäö #öl #läsa #drickaöl #tags #are #being #ignored"; 
preg_match_all($re, $str, $matches);
print_r($matches[0]);

也许,您可能还想使用 \p{L}(一种 Unicode 字母类别),但似乎没有必要,因为带有 u Unicode 标志的 \w 已经匹配所有 Unicode字母。 这是带有 \p{L}:

的正则表达式版本
$re = '/#[0-9_\p{L}]+/u';

IDEONE demo

您还可以使用 PCRE unicode 属性:\p{L}\p{N} 为此:

preg_match_all('/(#[\p{L}\p{N}_]+)/u', $content, $matches);

RegEx Demo