具有相同名称的正则表达式分组

Grouping of regex with same name

我正在尝试编写一个正则表达式以从 sting 中获取成分名称、数量和单位。该字符串可以是任何模式,例如“pohe 2 kg OR 2 Kg pohe OR 2Kg Pohe”。 我尝试使用以下代码 -

<?PHP
    $units = array("tbsp", "ml", "g", "grams", "kg", "few drops"); // add whatever other units are allowed
  
    
    //mixed pattern
    $pattern = '/(?J)(((?<i>^[a-zA-Z\s]+)(?<q>\d*\s*)(?<u>' . join("|", array_map("preg_quote", $units)) . '))|(?<q>^\d*\s*)(?<u>' . join("|", array_map("preg_quote", $units)) . ')(?<i>[a-zA-Z\s]+))/';

    
    $ingredients = '2kg pohe';
    
    preg_match_all($pattern, $ingredients, $m);
    print_r($m);
    $quantities = $m['q'];
    $units = array_map('trim', $m['u']);
    $ingrd = array_map('trim', $m['i']);
    print_r($quantities);
    print_r($units);
    print_r($ingrd);
?>

以上代码适用于字符串“2kg pohe”,但不适用于“pohe 2kg”。

如果有人知道我遗漏了什么,请帮助我。

对于 pohe 2kg 重复的命名组是空的,因为 preg_match_all 的文档指出对于标志 PREG_PATTERN_ORDER(这是默认值)

If the pattern contains duplicate named subpatterns, only the rightmost subpattern is stored in $matches[NAME].

在您生成的模式中,2kg pohe 的第二部分(交替后)有一个匹配项,但对于 pohe 2kg,第一部分只有一个匹配项,因此第二部分没有存储值。

你可能会做的是使用 PREG_SET_ORDER 标志,它给出:

$ingredients = '2kg pohe';
preg_match_all($pattern, $ingredients, $m, PREG_SET_ORDER);
print_r($m[0]);

输出

Array
(
    [0] => 2kg pohe
    [i] =>  pohe
    [1] => 
    [q] => 2
    [2] => 
    [u] => kg
    [3] => 
    [4] => 2
    [5] => kg
    [6] =>  pohe
)

$ingredients = 'pohe 2kg';
preg_match_all($pattern, $ingredients, $m, PREG_SET_ORDER);
print_r($m[0]);

输出

Array
(
    [0] => pohe 2kg
    [i] => pohe 
    [1] => pohe 
    [q] => 2
    [2] => 2
    [u] => kg
    [3] => kg
)

然后你可以获得两个字符串的命名子组,如 $m[0]['i'] 等。

注意示例中有2Kg,您可以使模式不区分大小写以进行匹配。