我希望捕获数字范围并将其替换为数字,但仅限于特定标记内。
$str = "This is some (the numbers are between 8, 9-12) and we have some 9-12 outside";
输出应为
$str = "This is some (the numbers are between 8, 9, 10, 11, 12) and we have some 9-12 outside";
我只需捕获9-12
,它位于括号之间,并且只替换括号外的9-12
。
答案 0 :(得分:1)
您可以使用preg_replace_callback
和基于\G
的模式执行此操作:
$str='This is some (the numbers are between 8, 9-12) and we have some 9-12 outside';
echo preg_replace_callback('~(?:\G(?!\A)|\()[^)0-9]*+(?:[0-9]++(?!-[0-9])[^)0-9]*)*+\K([0-9]++)-([0-9]+)~', function ($m) {
return implode(', ', range($m[1], $m[2]));
}, $str);
模式细节:
~
(?: # two possible beginnings
\G(?!\A) # position after the previous match
| # OR
\( # an opening parenthesis
)
[^)0-9]*+ # all that is not a closing parenthesis or a digit
(?:
[0-9]++ (?!-[0-9]) # digits not followed by an hyphen and a digit
[^)0-9]*
)*+
\K # the match result starts here
([0-9]++) # group 1
-
([0-9]+) # group 2
~
如果要限制获得匹配的步骤数,可以重写模式的开头:(?:\G(?!\A)|\()
,如下所示:\G(?:(?!\A)|[^(]*\()
。通过这种方式,模式在开括号之前不会再失败,但会很快达到它,从而避免(限制)模式开始时(大部分时间)失败交替的成本。
答案 1 :(得分:0)
试试这个:
preg_match_all('#\([^\)]+\)#', $str, $matches);
foreach ($matches as $m) {
$str = str_replace($m, str_replace('-', ', ', $m), $str);
}