具有相同名称的正则表达式分组
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
,您可以使模式不区分大小写以进行匹配。
我正在尝试编写一个正则表达式以从 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
,您可以使模式不区分大小写以进行匹配。