views:

71

answers:

3

I'm trying to replace the ~ into | between the [ ] in the folowwing case:

{stackoverflow is a [cool~great~fast] website ~ Find your answers [easily~quickly] on stackoverflow}.

Note: The text between the [ ] can be multiline.

I've tried multiple regexs buth with no luck.

My closest call at the moment is:

$text = preg_replace("/\[(.*?)~(.*?)\]/i", "[$1|$2]", $text);

But that returns

{stackoverflow is a [cool~great|fast] website ~ Find your answers [easily|quickly] on stackoverflow}.
A: 

What are some examples of the regexes you've used? My immediate thought is that [] is tripping you up because that is used to match character classes. If you want to match [ or ] as a literal you must escape it with backslashes: \[ or \].

Billy
My closest call was preg_replace("/\[(.*?)~(.*?)\]/i", "[\1|\2]", $text);But I'm getting a weird character instead of the text.
brechtvhb
the [] are escaped but stackoverflow removes the \ before it for some reason.
brechtvhb
@brechtvhb: You get the funny character because `\1` and `\2` mean different things in double quotes than in single quotes. If I use single quotes and escape the brackets, I get correct results for simple cases with your regex. However it does not work when there are multiple `~`s inside the brackets (only the first one in each bracket-pair will be replaced).
sepp2k
+1  A: 

You need to use one regex to find all strings in brackets and then another to replace the ~s in them. You can use preg_replace_callback to apply the ~-replacing regex to all the substrings in brackets like this:

preg_replace_callback('/\[[^\]]+\]/', function ($str) {
    return str_replace('~', '|', $str[0]);
}, $my_string)
sepp2k
Works :) Thanks a lot!
brechtvhb
I would use str_replace instead of preg_replace in the callback, as invoking any preg function is fairly costly, so you could use str_replace('~', '|', $str[0]) instead and get the same effect.
tsgrasser
@tsgrasser: Fair enough. Done.
sepp2k
+2  A: 

simpler than you think

 echo preg_replace('/~(?=[^\[\]]*\])/s', '|', $a);

?= is a lookahead assertion and reads "followed by". That is, "a tilde followed by some non-brackets and then a closing bracket" - this matches only ~'s inside [ ]

stereofrog
This would also replace the ~ in "~la]", i.e. it does not require an opening bracket to occur before the tilde. That's probably not a problem though, so +1.
sepp2k