Before a log lands in an analytics dashboard or a shared Slack channel, you want to scrub IP addresses out of it. What's the regex tool for replace?
re.sub(pattern, replacement, string) — I've seen the signature. Pattern to match, string to swap in, the input to scrub. What's the catch?
No catch. re.sub replaces every non-overlapping match by default, returning the new string. Strings are immutable, so it never mutates the original — you reassign:
import re
clean = re.sub(r"\b\d{1,3}(?:\.\d{1,3}){3}\b", "[IP]", line)That pattern is a tighter version of yesterday's IP matcher — (?:...) is a non-capturing group that lets you repeat .\d{1,3} three times.
Can I chain two re.sub calls — one for IPs, another for emails?
Yes, and that's the idiomatic approach. Each substitution handles one pattern cleanly. Don't cram them into one regex alternation — readability dies:
line = re.sub(IP_PATTERN, "[IP]", line)
line = re.sub(EMAIL_PATTERN, "[EMAIL]", line)Two focused calls beat one monster pattern.
What happens if the pattern matches nothing?
re.sub returns the original string unchanged. No error, no warning. So a line with no IPs passes through your sanitizer untouched. The function is safe to apply to every line without pre-checking whether a replacement is needed.
Three tools, three days. Search says yes-or-no. Findall extracts every match. Sub replaces every match. That's a whole vocabulary.
Regex is really four verbs: match, search, findall, sub. You've got three. That's enough to build real text-processing pipelines without ever needing to touch the rest.
re.sub(pattern, repl, string)TL;DR: replace every non-overlapping match with the replacement string; return a new string.
count=N — optional kwarg to cap replacements| Verb | Returns | Use for |
|---|---|---|
re.search | Match or None | presence check |
re.findall | list of matches | extraction |
re.sub | new string | replacement |
(?:...) is a non-capturing group — reuse a sub-pattern without capturing it.
Before a log lands in an analytics dashboard or a shared Slack channel, you want to scrub IP addresses out of it. What's the regex tool for replace?
re.sub(pattern, replacement, string) — I've seen the signature. Pattern to match, string to swap in, the input to scrub. What's the catch?
No catch. re.sub replaces every non-overlapping match by default, returning the new string. Strings are immutable, so it never mutates the original — you reassign:
import re
clean = re.sub(r"\b\d{1,3}(?:\.\d{1,3}){3}\b", "[IP]", line)That pattern is a tighter version of yesterday's IP matcher — (?:...) is a non-capturing group that lets you repeat .\d{1,3} three times.
Can I chain two re.sub calls — one for IPs, another for emails?
Yes, and that's the idiomatic approach. Each substitution handles one pattern cleanly. Don't cram them into one regex alternation — readability dies:
line = re.sub(IP_PATTERN, "[IP]", line)
line = re.sub(EMAIL_PATTERN, "[EMAIL]", line)Two focused calls beat one monster pattern.
What happens if the pattern matches nothing?
re.sub returns the original string unchanged. No error, no warning. So a line with no IPs passes through your sanitizer untouched. The function is safe to apply to every line without pre-checking whether a replacement is needed.
Three tools, three days. Search says yes-or-no. Findall extracts every match. Sub replaces every match. That's a whole vocabulary.
Regex is really four verbs: match, search, findall, sub. You've got three. That's enough to build real text-processing pipelines without ever needing to touch the rest.
re.sub(pattern, repl, string)TL;DR: replace every non-overlapping match with the replacement string; return a new string.
count=N — optional kwarg to cap replacements| Verb | Returns | Use for |
|---|---|---|
re.search | Match or None | presence check |
re.findall | list of matches | extraction |
re.sub | new string | replacement |
(?:...) is a non-capturing group — reuse a sub-pattern without capturing it.
Write `redact_ips(line)` that replaces every IPv4 address in the string with the literal text `"[IP]"`. Use `re.sub` with the pattern `r"\b\d{1,3}(?:\.\d{1,3}){3}\b"`.
Tap each step for scaffolded hints.
No blank-editor panic.