检测字符串中的@mentions 从一个匹配项中返回两个元素
Posted
技术标签:
【中文标题】检测字符串中的@mentions 从一个匹配项中返回两个元素【英文标题】:Detecting @mentions in a string returns two elements from one match 【发布时间】:2014-06-09 16:39:33 【问题描述】:我有以下代码:
$string = "Manual balls knit cardigan @120rb
ORDER
BB 28AFF6A6 atau 25AE5DB3
Phone 081298249949 atau 081310570229
Line indy2212 atau indy2281
FORMAT
Nama
Alamat
Telp
Kode barang";
if (preg_match('/(?<= )@([^@ ]+)/', $string, $matches))
var_dump(count($matches));
var_dump('first ' . $matches[0]);
var_dump('second ' . $matches[1]);
但是,这会导致 $matches
返回计数为 2 的数组。使用以下字符串:
2
@120rb ORDER BB
120rb ORDER BB
我的问题是为什么?为什么它匹配字符串两次?我的正则表达式有什么问题
【问题讨论】:
第一个元素是整个匹配,也就是 $0,而第二个元素是第一个内存捕获,也就是 $1。 @mickmackusa 好点,@[^@\s]+
would be better。我已经删除了原来的评论。
【参考方案1】:
preg_match()
将匹配项存储到您作为第三个参数提供的数组中。在这种情况下,您的 preg_match()
语句如下所示:
preg_match('/(?<= )@([^@ ]+)/', $string, $matches);
所以$matches
包含所有匹配项,其中:
$matches[0]
将包含与完整模式匹配的文本
$matches[1]
将具有与第一个捕获组匹配的文本
$matches[2]
将具有与第二个捕获组匹配的文本
等等……
这里的正则表达式是(?<= )@([^@ ]+)
。它完全匹配@120rb ORDER BB
,所以它会存储在$matches[0]
,而捕获组([^@ ]+)
只会捕获@
(120rb ORDER BB
)之后的部分,它将存储在$matches[1]
。
目前,正则表达式不检测提及是否在字符串的开头。此外,它会错误地匹配下一行的空格,因为[^@]
将匹配任何不是@
符号的东西。我会在preg_match_all()
中使用以下表达式:
(?<=^|\s)@([^@\s]+)
代码:
if (preg_match_all('/(?<=^|\s)@([^@\s]+)/', $string, $matches))
print_r($matches[1]);
要获得匹配的数量,你可以使用echo count($matches[0]);
。
Demo
【讨论】:
那么我该如何更改它以便我想跟踪我的字符串中有多少提及? @aditcount($matches[0])
.
@adit 您可以将您的字符串 + 正则表达式发布到 regex101.com 并发送一个永久链接(点击左侧的软盘)吗?【参考方案2】:
preg_match()
和preg_match_all()
都允许将引用变量赋值为它们的第三个参数。如果您提供变量,则默认行为是将全字符串匹配项放在其第一个元素中。
当您只想提取模式的完整字符串匹配的最后一部分时,可以使用\K
丢弃前导/不需要的字符。这避免了后视的费用。
preg_match()
和 preg_match_all()
都提供找到的全字符串匹配的数量作为它们的返回值。这意味着永远不需要在matches数组上调用count()
。
我下面的模式会匹配字符串的起始位置(^
)或空白字符(\s
),然后匹配文字@
符号,然后忘记这些匹配的字符,然后匹配一个或多个“单词字符”,由字母、数字和下划线组成。此模式应消除错误匹配,例如电子邮件地址和未提及。
如果您需要确保提及后不会立即出现无效字符,您可以在模式的末尾写一个前瞻来要求字符串的结束位置或空白字符 ((?=$|\s)
)。
代码:(Demo)
$string = '@mention_1 @$badmention Manual balls knit cardigan @120rb
email me @ example@example.com';
$count = preg_match_all(
'/(?:^|\s)@\K\w+/',
$string,
$matches
);
var_export([
'count' => $count,
'matches' => $matches[0]
]);
输出:
array (
'count' => 2,
'matches' =>
array (
0 => 'mention_1',
1 => '120rb',
),
)
【讨论】:
以上是关于检测字符串中的@mentions 从一个匹配项中返回两个元素的主要内容,如果未能解决你的问题,请参考以下文章