To be explicit: the reason "2x2x2" turns into "2y2x2" is because your expression first matches "2x2" , replaces it with "2y2" , and then resumes the search after this match is found. The next bit is "x2" , which does not match your pattern.
The reason for @xdazz's solution is that look-around statements do not actually consume string characters. The part matched on the line is "x" when it is preceded and followed by numbers.
By the way, changing @xdazz from [0-9] to \d does not change very much, but it is slightly different: \d will also correspond to other Unicode characters, which are considered digits, while [0-9] only matches the exact 10 characters in given range.
source share