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.


 "BBB  afsdfsdfs  OneB  sdfjsdfsdf BB sdfsadfasdf  OneB" 


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.


"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.

  • $\begingroup$ What specific results do you expect? $\endgroup$
    – Silvia
    Jun 17, 2013 at 19:55
  • $\begingroup$ @Silvia "B" -> " OneB " with some condition. $\endgroup$ Jun 18, 2013 at 0:24

2 Answers 2


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


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" *)
  • $\begingroup$ 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 $\endgroup$ Jun 18, 2013 at 0:44
  • $\begingroup$ @HyperGroups Indeed. Have edited to fix. $\endgroup$
    – wxffles
    Jun 18, 2013 at 1:37

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"}]


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


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.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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