Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

StringReplace and search out of one pattern

replace[str_] := StringReplace[ result1 = StringReplace[str, rulesTemp = {"BB"
-> "TwoA", "BBB" -> "ThreeB"}], {"B" -> " OneB ", Sequence @@ Reverse /@ rulesTemp}]

case 1


replace["BBB afsdfsdfs B sdfjsdfsdf BB sdfsadfasdf B"]
(*BB OneB  afsdfsdfs  OneB  sdfjsdfsdf BB sdfsadfasdf  OneB *)

The first "OneB"in "BB OneB..." is not expected.

Expect:

 "BBB  afsdfsdfs  OneB  sdfjsdfsdf BB sdfsadfasdf  OneB" 

case2


replace["BBBaf\\Left sdfsdfsBsdfjsdf\\Right sdfBBsdfsadfasdfB"]
(*BB OneB af\Left sdfsdfs OneB sdfjsdf\Right sdfBBsdfsadfasdf OneB *)

The above result is not expected.

I'd like only isolated "B" (not "BB" or "BBB...") to be replaced by "OneB".

And in case 2, "B" in one StringPattern \\Left sdfsdfsBsdfjsdf \\Right should be ignored.

Expect:

"BBB af\\Left sdfsdfsBsdfjsdf\\Right sdfBBsdfsadfasdf OneB "

case3 ignore one repeated pattern


replace["BBBaf\\Left sdfsdfsBsdfjsdf\\Right sdfBBsd\\Left sdfsdfsBsdfjsdf\\Right fsadfasdfB"]
(*BB OneB af\Left sdfsdfs OneB sdfjsdf\Right sdfBBsd\Left sdfsdfs OneB sdfjsdf\Right fsadfas
df OneB *)

Maybe should use Except or other.

share|improve this question
    
What specific results do you expect? –  Silvia Jun 17 '13 at 19:55
    
@Silvia "B" -> " OneB " with some condition. –  HyperGroups Jun 18 '13 at 0:24
add comment

2 Answers 2

up vote 2 down vote accepted

If I understand the question correctly, you want to replace "B", but not if it is next to another "B", and not if it is between "\Left" and "\Right".

Here is how I would find the isolated "B":

firstB = StartOfString ~~ "B" ~~ post:Except["B"] :> "oneB" ~~ post;
lonelyB = pre:Except["B"] ~~ "B" ~~ post:Except["B"] :> pre ~~ "oneB" ~~ post;
lastB = pre:Except["B"] ~~ "B" ~~ EndOfString :> pre ~~ "oneB";

And this is how I would avoid the "\Left" and "\Right":

leftright = lr : Shortest["\\Left" ~~ ___ ~~ "\\Right"] :> lr

Testing:

StringReplace["BBB afsdfsdfs B sdfjsdfsdf BB sdfsadfasdf B",
  {firstB, lonelyB, lastB, leftright}]
(* "BBB afsdfsdfs oneB sdfjsdfsdf BB sdfsadfasdf oneB" *)

StringReplace["BBBaf\\Left sdfsdfsBsdfjsdf\\Right sdfBBsdfsadfasdfB",
  {firstB, lonelyB, lastB, leftright}]
(* "BBBaf\\Left sdfsdfsBsdfjsdf\\Right sdfBBsdfsadfasdfoneB" *)
share|improve this answer
    
You got my question. The use of Longest in leftrightwill fail in this case "BBBaf\\Left sdfsdfsBsdfjsdf\\Right sdfBBsfgsdfgBdsfgdgfd\\Left sdfsdfsBsdfjsdf\\Right sadfasdfB", need Shortest –  HyperGroups Jun 18 '13 at 0:44
    
@HyperGroups Indeed. Have edited to fix. –  wxffles Jun 18 '13 at 1:37
add comment

It seems that Mathematica goes through the string from left to right, seeing if the first character of it may match any of the specified string patterns. Compare

StringReplace["tB", {"B" -> "C", "tB" -> "2B"}]

"2B"

StringReplace["BB", {"B" -> "C", "BB" -> "2B"}]

"CC"

I thought it might be decided by specificity, but it turns out that is not the case. That is, Mathematica does not consider every substring and decide the most specific pattern that matches it and then applies a rule.

Here is my take on how it does work. Mathematica seems to go through the string from left to right. When it finds a character that may be the start of a substring that matches a pattern, it continues to look at the characters after that until it matches the pattern or it concludes that this character was not the start of this pattern after all. If the substring found this way matches the pattern, it makes the replacement. The first pattern considered is the first element of list of rules.

Maybe that was your confusion too.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.