Options to Replace String in Large Scale
2023-10-25 #engineering #emacs
10 years ago, when I became a software engineer, my mentor showed me how to replace all occurrences of a string (or a regex) under a large codebase effectively with a tool called codemod. It turned out to be one of the most useful text-editing techniques in my next 10 years, saving me many hours of “find and replace” manually.
Over time, I discovered additional options for different use cases. Here they are.
For Simple Replacement - sed
sed
is my favorite for simple cases because it comes pre-installed in most operating systems.
# replace all instances of `foo` (regex) with `bar` (regex) in a file
sed -i "s/foo/bar/g" path/to/file
# replace all instances of `foo` (regex) with `bar` (regex) found by `find`
find . -name '*.cpp' | xargs sed -i "s/foo/bar/g"
# replace all instances of `foo` (regex) with `bar` (regex) in modified files under git
git diff --name-only | xargs sed -i "s/foo/bar/g"
If I encounter a performance issue, I will switch to fastmod
.
For Very Large Code Base - fastmod
fastmod is a fast partial replacement for codemod. It is written in Rust and is designed for large-scale codebase refactoring.
# replace a regex pattern in specific files or directories:
fastmod 'foo' 'bar' -- {{path/to/file path/to/directory ...}}
To install, run cargo install fastmod
, assume you have Rust’s Cargo installed.
For more use cases, see tldr:fastmod.
For Simple Replacement in Emacs - dired
As an Emacser, I must also provide a way to achieve this in Emacs.
- M-x dired
- Mark the required files and directories (
m
to select,t
to toggle all) - Press
Q
(dired-do-find-regexp-and-replace
) to replace string by regex- Press
y
to accept. - Press
!
to accept all.
- Press
For Interactive Replacement in Emacs - wgrep
wgrep
stands for “Writable Grep Buffer”. It is a very flexible interactive replacement in Emacs. It gathers all occurrences in a buffer and then you can use whatever you want edit them.
- Search with
counsel
, e.g.,counsel-rg
- C-c C-o (
ivy-occur
) - C-x C-q (
ivy-wgrep-change-to-wgrep-mode
) - Edit (e.g.,
replace-regex
) - C-c C-c (commit the changes)
For more details on this method, see:
For Interactive Replacement in Emacs Project - project-query-replace-regex
project.el
provides a command called project-query-replace-regex
(default keybinding: C-x p r
) that allows you to interactively replace a regex pattern within a project.
Epilogue
In most cases, I prefer sed
and fastmod
since they allow me to do it in a single command, which makes it easier to iterate the desired command (execute and revert for the right “foo” and “bar”).