Hmm, your regular expression is suspicious.
,"([.*]*,[.*]*)*",
[.*] will match a literal dot or asterisk ( . and * become literals in character classes).
In addition, if this could actually correspond to something in the line, you could replace only one comma, because the rest of the line (including the comma) would be consumed by the regular expression and once consumed, cannot be replaced again if you did not run loop until no commas are added.
What you can do with re.sub and replace these commas is to use the return paths (you can do this, enough documentation about them, I think). If you have only one pair of double quotes, you can make sure that only commas are replaced, followed by one double quote:
,(?=[^"]*"[^"]*$)
[^"] means a character that is not a double quote. [^"]* means that it will be repeated 0 or more times.
$ means end of line.
Now, lookahead (?= ... ) guarantees that there is something inside the comma.
See the commas that match here .
After that, you can simply replace the commas with whatever value you want.
str = re.sub(r',(?=[^"]*"[^"]*$)', '@', str)
If, however, there are several double quotes, you must ensure that there is an odd number of double quotes ahead. This can be done using regex:
,(?=[^"]*"[^"]*(?:"[^"]*"[^"]*)*$)
(?: ... ) , by the way, is a group without capture.