replacing substrings in regex matches with preg_match_all()
Posted: Thu Dec 20, 2007 1:22 am
The preg_replace() function can only replace the full pattern matches. Yes you do have access to the captured substrings and can manipulate them/move them around, but only to replace the full pattern match that it found. I needed a way to replace substrings within the full pattern matches, so I could truly harness the power of regex.
For example, think about how you would replace the second 'l' in hello with something and then replace the first 'l' in laugh with something else:
'hello lalala look over there like to laugh long listen to the large loose'
but with regex you could easily identify those specific l's
'/hel(l)o lalala look over there like to (l)augh long listen to the large loose/'
anyways here' s my solution to replacing substrings from regex matches, i'd like to hear any feedback on better methods of doing this/things to enhance the function
For example, think about how you would replace the second 'l' in hello with something and then replace the first 'l' in laugh with something else:
'hello lalala look over there like to laugh long listen to the large loose'
but with regex you could easily identify those specific l's
'/hel(l)o lalala look over there like to (l)augh long listen to the large loose/'
anyways here' s my solution to replacing substrings from regex matches, i'd like to hear any feedback on better methods of doing this/things to enhance the function
Code: Select all
<?php
function preg_replace_subs($pat,$hay,$replaceArr, $out = false) {
# ie for replaceArr: array(2 => 'two', 4 => 'four')
//$out must have 1 flag set which is offset capture
if (empty($replaceArr)) {
die('<br><b>Error:</b><br>Replace Array argument cannot be empty');
}
$matches = true;
if (!$out) {
$matches = preg_match_all($pat, $hay, $out, PREG_OFFSET_CAPTURE);
}
if ($matches && !empty($out[0])) {
$hayChars = str_split($hay);
unset($out[0]);
foreach ($out as $subKey => $subArr) { //each sub $1 -...
if (isset($replaceArr[$subKey])) {
foreach ($subArr as $subInfo) { //each match of this sub
$sub = $subInfo[0];
$subOff = $subInfo[1];
$subLen = strlen($sub);
if (isset($hayChars[$subOff])) {
if ($subLen > 1) {
//del rest of positions where old sub existed
for ($x = $subOff+1; $x<=(($subOff+$subLen)-1); $x++) {
unset($hayChars[$x]);
}
}
//replace substring
$hayChars[$subOff] = $replaceArr[$subKey];
} else {
die('<br><b>Error:</b><br>Cannot replace '.htmlentities($sub).' because it exists in another substring which has already been replaced.');
}
}
}
}
return implode('',$hayChars);
} else {
return false;
}
}
$pat = '~(hello (<b>)) it is a (wonderful)</b> day<c> (ou(tsi)de) (so lovely)~';
$hay = 'hello <b> it is a wonderful</b> day<c> outside so lovely
hello <b> it is a wonderful</b> day<c> outside so lovely';
$rArr[2] = 'two';
$rArr[4] = 'four';
echo htmlentities(preg_replace_subs($pat,$hay,$rArr));
//outputs: hello two it is a wonderful</b> day<c> four so lovely hello two it is a wonderful</b> day<c> four so lovely
?>