If a string contains foo
, replace foo
with bar
. Otherwise, append bar
to the string. How to write this with one single re.sub
(or any other function) call? No conditions or other logic.
import re
regex = "????"
repl = "????"
assert re.sub(regex, repl, "a foo b") == "a bar b"
assert re.sub(regex, repl, "a foo b foo c") == "a bar b bar c"
assert re.sub(regex, repl, "afoob") == "abarb"
assert re.sub(regex, repl, "spam ... ham") == "spam ... hambar"
assert re.sub(regex, repl, "spam") == "spambar"
assert re.sub(regex, repl, "") == "bar"
For those curious, in my application I need the replacement code to be table-driven - regexes and replacements are taken from the database.
This is tricky. In Python, replacement text backreferences to groups that haven't participated in the match are an error, so I had to build quite a convoluted construction using lookahead assertions, but it seems to pass all the test cases:
result = re.sub("""(?sx)
( # Either match and capture in group 1:
^ # A match beginning at the start of the string
(?:(?!foo).)* # with all characters in the string unless foo intervenes
$ # until the end of the string.
| # OR
(?=foo) # The empty string right before "foo"
) # End of capturing group 1
(?:foo)? # Match foo if it's there, but don't capture it.""",
r"\1bar", subject)
Try this simple one-liner, no regexp, no tricks:
a.replace("foo", "bar") + (a.count("foo") == 0) * "bar"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With