dsaba Posted December 17, 2007 Share Posted December 17, 2007 <?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 Quote Link to comment Share on other sites More sharing options...
dsaba Posted December 17, 2007 Author Share Posted December 17, 2007 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. Quote Link to comment Share on other sites More sharing options...
dsaba Posted December 17, 2007 Author Share Posted December 17, 2007 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. Quote Link to comment Share on other sites More sharing options...
rajivgonsalves Posted December 17, 2007 Share Posted December 17, 2007 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); ?> Quote Link to comment Share on other sites More sharing options...
rajivgonsalves Posted December 17, 2007 Share Posted December 17, 2007 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); ?> Quote Link to comment Share on other sites More sharing options...
dsaba Posted December 17, 2007 Author Share Posted December 17, 2007 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??? Quote Link to comment Share on other sites More sharing options...
rajivgonsalves Posted December 18, 2007 Share Posted December 18, 2007 try this <?php function fnHighlight($strHighlight) { return "<span style='background-color: #FFFF00;'>".htmlentities($strHighlight)."</span>"; } $raw = '(h)ello how are yo(u) (d)oing'; $raw = preg_replace("/\((.*?)\)/ie","fnHighlight($1)",$raw); print $raw; ?> Quote Link to comment Share on other sites More sharing options...
dsaba Posted December 19, 2007 Author Share Posted December 19, 2007 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.... Quote Link to comment Share on other sites More sharing options...
dsaba Posted December 20, 2007 Author Share Posted December 20, 2007 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 ?> Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.