Chcę uchwycić zakres liczb i zastąpić go liczbami, ale tylko w obrębie określonego znacznika.
$str = "This is some (the numbers are between 8, 9-12) and we have some 9-12 outside";
Wynik powinien być
$str = "This is some (the numbers are between 8, 9, 10, 11, 12) and we have some 9-12 outside";
Muszę tylko uchwycić 9-12
, który znajduje się między nawiasami i tylko go nie zastępuj 9-12
poza nawiasami.
Odpowiedzi:
1 dla odpowiedzi № 1Możesz to zrobić w ten sposób preg_replace_callback
i a G
wzór oparty:
$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);
Szczegóły wzoru:
~
(?: # 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
~
Jeśli chcesz ograniczyć liczbę kroków w celu uzyskania dopasowania, możesz przepisać początek wzorca: (?:G(?!A)|()
lubię to: G(?:(?!A)|[^(]*()
. W ten sposób wzorzec nie zawiedzieaż do nawiasu otwierającego, ale szybko do niego dojdzie, unikając (ograniczając) koszt (przez większość czasu) nieudanej zmiany na początku wzorca.
0 dla odpowiedzi nr 2
Spróbuj tego:
preg_match_all("#([^)]+)#", $str, $matches);
foreach ($matches as $m) {
$str = str_replace($m, str_replace("-", ", ", $m), $str);
}