Find every match, then extract or replace
find() returns the position of a piece of text, or -1 when it isn't there; find(piece, start) looks again from a later position. Positions let you extract what sits between markers or rebuild the text around each match.
- Use
findand check for -1 before slicing with the result - Find every occurrence by calling
findagain from just after the last match - Extract text between two markers, and rebuild text around matches
in answers *is it there?*. find answers *where?*: text.find("@") is the position of the first @, or -1 if there is none. Positions are what slicing needs, so find is how you cut a value out of a text: the domain after @, the order number after #.
The -1 is the trap. It is a valid slice position (it means *the last character*), so using it without checking silently gives a wrong piece instead of an error.
Run each example to see what it prints. Running examples doesn't count toward progress.
def domain(email): """Return the part after @ in lower case, or None if there is no @.""" at = email.find("@") if at == -1: return None return email[at + 1:].strip().lower() print(domain("jamal.walker62@iCloud.com")) print(domain("not an email")) note = "Refund for order #O104839 approved" start = note.find("#") print(note[start + 1:start + 8]) missing = "no order number here" print(missing[missing.find("#") + 1:])
find takes an optional start position: text.find("fee", 10) searches from position 10 on. To find every occurrence, loop: find from 0, record the position, then find again from just after it, until find returns -1. With those positions you can rebuild the text: copy everything up to a match, add something new, and continue after the match. replace does the simplest version of this for you when the piece is exact.
def positions(text, piece): """Return every position where piece starts in text.""" found = [] start = text.find(piece) while start != -1: found.append(start) start = text.find(piece, start + len(piece)) return found complaint = "late fee charged, then another fee, fee waived?" print(positions(complaint, "fee")) print(positions(complaint, "refund")) print(complaint.replace("fee", "FEE", 2))
When to use it: to pull a value out from between markers, to locate every match, and to change text around matches. Mistakes to avoid:
- Slicing with a
findresult without checking for -1. - Restarting the search at the same position, which loops forever.
- Forgetting that
findandreplaceare case-sensitive; search a lowered copy when case shouldn't matter, but slice the original.
findreturns a position or -1; check for -1 before slicing.find(piece, start)searches fromstart; loop from just after each match to find them all.- Search a lowered copy when case doesn't matter, but slice the original text.
- Next: count characters and words, and compare texts by their counts.