示例字符串:
accuracy-is-5
accuracy-is-5-or-15
accuracy-is-5-or-15-or-20
package-is-dip-8-or-dip-4-or-dip-16
我当前的正则表达式:
/^([a-z0-9\-]+)\-is\-([a-z0-9\.\-]*[a-z0-9])(?:\-or\-([a-z0-9\.\-]*[a-z0-9]))*$/U
没有固定长度,部分:
\-or\-[a-z0-9\.\-]
可以重复。
Bot现在从字符串“precision-is-5-or-15-or-20”获得:
Array ( [0] => accuracy-is-5-or-15-or-20 [1] => accuracy [2] => 5 [3] => 20 )
15岁在哪里? :) Tnx。
答案 0 :(得分:5)
^\w+(?:-[a-zA-Z]+)+\K|\G(?!^)-(\d+)(?:(?:-[a-zA-Z]+)+|$)
您可以在此处使用\G
来捕获所有组。无论何时重复捕获组,最后一个值都会覆盖之前的。请参阅演示。
https://regex101.com/r/tS1hW2/3
\ G在上一场比赛结束时断言位置或第一场比赛的字符串开头
编辑:
^\w+-is(?:-dip)?\K|\G(?!^)-(\d+)(?:-or(?:-dip)?|$)
如果您确定is,or and dip
,可以使用此功能。请参阅演示。
https://regex101.com/r/tS1hW2/4
$re = "/^\\w+-is(?:-dip)?\\K|\\G(?!^)-(\\d+)(?:-or(?:-dip)?|$)/m";
$str = "accuracy-is-5\naccuracy-is-5-or-15\naccuracy-is-5-or-15-or-20\npackage-is-dip-8-or-dip-4-or-dip-16";
preg_match_all($re, $str, $matches);
答案 1 :(得分:3)
当在模式中重复捕获组时,先前的值将被最后一个值覆盖。因此,无法使用preg_match
设计您的模式。
可能的解决方法包括使用preg_match_all
搜索模式的所有匹配项以及\G
锚点,该锚点是上一次匹配后的位置。必须编写模式以一次找到一个值。
\G
确保所有匹配都是连续的。为了确保已到达字符串的结尾(换句话说,字符串从开始到结尾都是正确格式化的),一种方便的方法是在结尾处创建一个空的捕获组。因此,如果此捕获组出现在最后一个匹配中,则表示格式正确。
define('PARSE_SENTENCE_PATTERN', '~
(?: # two possible beginings:
\G(?!\A) # - immediatly after a previous match
| # OR
\A # - at the start of the string
(?<subject> \w+ (?>[-.]\w+)*? ) -is- # (in this case the subject is captured)
)
(?<value> \w+ (?>[-.]\w+)*? ) # capture the value
(?: -or- | \z (?<check>) ) # must be followed by "-or-" OR the end of the string \z
# (then the empty capture group "check" is created)
~x');
function parseSentence ($sentence) {
if (preg_match_all(PARSE_SENTENCE_PATTERN, $sentence, $matches, PREG_SET_ORDER) &&
isset(end($matches)['check']) )
return [ 'subject' => $matches[0]['subject'],
'values' => array_reduce ($matches, function($c, $v) {
$c[] = $v['value']; return $c; }, $c = []) ];
return false; // wrong format
}
// tests
$test_strings = ['accuracy-is-5', 'accuracy-is-5-or-15', 'accuracy-is-5-or-15-or-20',
'package-is-dip-8-or-dip-4-or-dip-16',
'bad-format', 'bad-format-is-', 'bad-format-is-5-or-'];
foreach ($test_strings as $test_string) {
var_dump(parseSentence($test_string));
}