Jump to content

[SOLVED] replacing substrings with other strings with regex or preg_replace()


dsaba

Recommended Posts

<?php
$raw = 'hello how are you';
$pat = '~hello (h)ow are yo(u)~';
preg_match_all($pat, $raw, $out);
print_r($out);
?>

 

will return this array:

Array
(
    [0] => Array
        (
            [0] => hello how are you
        )

    [1] => Array
        (
            [0] => h
        )

    [2] => Array
        (
            [0] => u
        )

)

 

 

I want to replace the substrings $out[1][0] and $out[2][0] with other strings

I want 'h' to be replaced with 'replacedH' and 'u' to be replaced with 'replacedU'

How can I do this at all, and how can I do this with preg_replace() ?

It seems that preg_replace() is only good for moving substrings around, but not for actually replacing the substrings with other strings.

 

notice if I use str_replace() it will also replace the other h's in the haystack, which i dont want replaced

 

so the final output I want should be:

'hello replacedHow are yoreplacedU'

-thank you

 

Link to comment
Share on other sites

someone mentioned why not use str_replace or substr_replace()

 

Well with str_replace() it will also replace the 'h' in 'hello' which i dont want to replaced

For substr_replace() it is the same as str_replace() except that you can start replacing at a certain offset.

As for finding the offset to begin with someone recommended using str_pos(), but of course str_pos() would also match the first 'h' in 'hello' which I don't want.

 

The only idea I have is if I could somehow get the regex engine to tell me in what pos it finds the substrings within the whole pattern match, then I could apply substr_replace() quite easily.

OR: If I could somehow split the whole pattern match at the offsets where the substrings begin, I could identify the substring positions within the whole pattern match as well. Simply using explode won't cut it yet again...

 

Taking all that into consideration.. All I am looking for is a universal method/algorithim to replace substrings in regex patterns with other strings.

Any ideas? C'mon gurus. :)

Link to comment
Share on other sites

ok here's an idea, you can run the substrings the regex finds through functions, the only problem is you can't call the part of the regex pattern that is NOT a substring, so in order to piece the whole pattern match together again you will have to place everything that is not in substrings into substrings, and then manipulate the chosen substrings and piece it back together, like so:

<?php
$raw = 'hello how are you';
$pat = '~(hello )(h)(ow are yo)(u)~';

$output = preg_replace($pat,'$1'.str_replace('$2','replacedH','$2').'$3'.str_replace('$4','replacedU','$4'),$raw);
echo $output;
?>

 

any better ideas? Because this would require to parse through the original regex pattern and basically put everything that doesn't have parenthesis into parenthesis.

Link to comment
Share on other sites

try this  :)

 

<?php
$raw = 'hello how are you doing';
$pat = '~\b(h)ow|Yo(u)|(d)oing$~ie';
$arrReplacement = array("h"=>"replaceH","u"=>"replaceU","d"=>"replaceD");

function fnPatternReplace($strRaw,$strPattern,$arrReplaceMent)
{
preg_match_all($strPattern,$strRaw,$arrMatches);

for ($i=0;$i<count($arrMatches[0]);$i++)
{
	$strRaw = str_replace($arrMatches[0][$i],str_replace($arrMatches[$i+1][$i],$arrReplaceMent[$arrMatches[$i+1][$i]],$arrMatches[0][$i]),$strRaw);
}

return $strRaw;
}

echo fnPatternReplace($raw,$pat,$arrReplacement);

?>

Link to comment
Share on other sites

better still try this

 

<?php
$raw = 'hello how are you doing';
$arrPat = array('(h)ow','Yo(u)','(d)oing');
$arrReplacement = array("h"=>"replaceH","u"=>"replaceU","d"=>"replaceD");

function fnPatternReplace($strRaw,$arrPattern,$arrReplaceMent)
{
$strPattern = "~\b".implode("\b|\b",$arrPattern)."\b~ei";
preg_match_all($strPattern,$strRaw,$arrMatches);

for ($i=0;$i<count($arrMatches[0]);$i++)
{
	$strRaw = str_replace($arrMatches[0][$i],str_replace($arrMatches[$i+1][$i],$arrReplaceMent[$arrMatches[$i+1][$i]],$arrMatches[0][$i]),$strRaw);
}

return $strRaw;
}

echo fnPatternReplace($raw,$arrPat,$arrReplacement);

?>

Link to comment
Share on other sites

thank you very much for your hard work and reply/interest

I'm going to study/try out your code....

yet, could you explain how this is a universal method for replacing substrings with other strings in a pattern? This is what i was originally looking for.

 

on this part:

$arrPat = array('(h)ow','Yo(u)','(d)oing');

$arrReplacement = array("h"=>"replaceH","u"=>"replaceU","d"=>"replaceD");

 

I don't see how this is very dynamic. Because all I will know will be which substring array numbers like, $1 or $2 that I want replaced and the strings i want to replace them with, the actual substring content will be unknown and dynamic.

 

Correct me if i'm wrong, but I think your method relies on me knowing what exactly is in the substrings i want to replace beforehand.

 

The reason why I wanted to replace substrings found in regex patterns with something else is because I wanted to highlight substrings found in a haystack that were found via regex for my ajax regex tester. But of course, this has many applications. So basically i would like to replace the original substrings with html that changes the text color (highlighting them). Am I crazy or something, or can this be done? I haven't gotten many replies to this thread from any of the "gurus" around here, and haven't gotten an exact solution or reply, so I can only assume that this is not posssible. so is it???

Link to comment
Share on other sites

The only idea I have is if I could somehow get the regex engine to tell me in what pos it finds the substrings within the whole pattern match, then I could apply substr_replace() quite easily.

wow I spent at least 2 good days working on a solution for this... with my parenthesis idea.. ingenious really

later I found out:

"PREG_OFFSET_CAPTURE" from the preg_match_all() captures the offset of substrings as well

 

I was thinking why wouldn't a feature like this be built in.. well it is

 

at least some of my work did not go in vain though.....

 

 

if someone pointed this out to me a while ago....sheesh....

Link to comment
Share on other sites

my solution:

 

<?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);
				//echo "replacing $sub<br>at offset: $subOff<br>it is $subLen long<br>";
				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 {
					//o($hayChars,100,100);
					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
?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.