Mark Baker Posted March 15, 2009 Share Posted March 15, 2009 I have a string in the format: '1 { A } 2 { N } "B { 3 } C" 4 { 5 } 6 "E { 7 } F" 8 { G } 9 { H }' and want to replace every occurrence of { with an X, and every occurrence of } with a Y, except when these values are within double quote marks, so the above example should give me: '1 X A Y 2 X N Y "B { 3 } C" 4 X 5 Y 6 "E { 7 } F" 8 X G Y 9 X H Y' I can do this using a normal str_replace() by exploding the string to an array on the double quote, and only replacing in odd numbered array entries, then imploding the string again. $temp = explode('"',$input); $i = 0; foreach($temp as $key => $value) { if (($i++ % 2) == 0) { $temp[$key] = str_replace($replaceFrom,$replaceTo,$value); } } $result = implode('"',$temp); However, while this gives me exactly what I need, it doesn't seem to be an efficient method; so I've been trying to work out a regexp that will locate each { or } within the string, count back the number of double quotes between that and the beginning of the string, and if it's an odd number do the replacement: $pregReplaceFrom = array( '/^(.*\".*){0,2}\{/', '/^(.*\".*){0,2}\}/' ); $pregReplaceTo = array( '$1X', '$1Y' ); $result = preg_replace($pregReplaceFrom,$pregReplaceTo,$input); However, this only replaces the last instances of { and } in my input, and adjusting {0,2} to {0,2,4,6,8} doesn't even replace that set... and doesn't seem a good way to do a count. Similarly: '/^(.*(\".*){0,2})\{/', '/^(.*(\".*){0,2})\}/' replaces the last set of braces only, and increasing the {0,2} results in no replacements. Ungreedy with {0,2} replaces the first set of braces only, and again increasing the {0,2} results in no replacements. Is what I'm trying to achieve feasible using a single preg_replace? and if so, what am I doing wrong? And is it likely to be a situation where my str_replace through the odd elements of an exploded string is the better approach anyway? Quote Link to comment Share on other sites More sharing options...
.josh Posted March 15, 2009 Share Posted March 15, 2009 You need to be able to check what's around it without actually matching anything, so that the other instances will be able to have something to match against. Lookaround to the rescue! $string = preg_replace('~(?<!"\w ){ (\w) }(?! \w")~',"X $1 Y",$string); 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.