Find and replace in a codebase | Hugonweb Annotated Link Bibliography
https://will-keleher.com/posts/5-Useful-Bash-Patterns.html
I never really have figured this out before. Here is a way:
grep -l pattern | xargs sed -ri 's|pat(tern)|\1s are birds|g'
The -l option to grep (and ripgrep) makes it just output filenames containing matches. The sed option -r enables extended regex (-E may alternatively be used like in grep), and -i replaces in place.
If any filenames contain spaces, newlines, or quotes, then xargs can get messed up. Terminating lines with null characters fixes that:
grep -lZ pattern | xargs -0 sed -ri 's|pat(tern)|\1s are birds|g'
or
rg -l0 pattern | xargs -0 sed -ri 's|pat(tern)|\1s are birds|g'