1

I have the following code:

$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]);
}

However this results in $matches to return an array of count 2. With the following string:

2
@120rb ORDER BB
120rb ORDER BB

My question is why? Why does it match the string twice? What is wrong with my regex

4

2 回答 2

3

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]);.

演示

于 2014-04-24T11:59:02.207 回答
0

两者都preg_match()允许preg_match_all()将引用变量赋值为它们的第三个参数。如果您提供变量,则默认行为是将全字符串匹配项放在其第一个元素中。

当您只想提取模式的完整字符串匹配的最后一部分时,可以使用\K丢弃前导/不需要的字符。这避免了后视的费用。

两者都preg_match()提供preg_match_all()找到的全字符串匹配的数量作为它们的返回值。这意味着永远不需要调用count()匹配数组。

我下面的模式将匹配字符串的起始位置(^)或空白字符(\s),然后匹配一个文字@符号,然后忘记这些匹配的字符,然后匹配一个或多个由字母、数字和下划线组成的“单词字符” . 此模式应消除错误匹配,例如电子邮件地址和未提及。

如果您需要确保提及后不会立即出现无效字符,您可以在模式的末尾写一个前瞻来要求字符串的结束位置或空白字符 ( (?=$|\s))。

代码:(演示

$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',
  ),
)
于 2021-10-30T21:07:45.663 回答