Quick tip: Replacing text with sed

Sometimes you may find yourself needing to replace multiple occurrences of some string or expression in one or more text files. Recently I found myself in one of those scenario's, which inspired this short post.

The problem at hand was the fact that property declarations in a fairly large Objective-C project didn't follow the same order when it came to defining atomicity and retain type. To make all declarations match the same order, each occurrence of <retain type>, nonatomic needed to be rewritten to nonatomic, <retain type>, where retain type is either weak or strong.

For a single file, the sed command would be:

sed -E -i '' 's/(weak|strong), nonatomic/nonatomic, \1/g' AwesomeHeaderFile.h  

Note: the i '' flag is only needed on OS X.

But as mentioned, this particular project had already grown quite a bit. Also, property declarations usually aren't limited to just header files. Implementation files also often contain private and protected property declarations, while you still have to deal with submodules you don't want to touch. To replace all occurrences ​of the given expression, in all .m and .h files, limited to just the current directory, the command would look something like this:

find . -type f -maxdepth 1 -iname "*.h" -o -iname "*.m" -print0 | xargs -0 sed -E -i '' 's/(weak|strong), nonatomic/nonatomic, \1/g'  

The find command compiles a (potentially) huge list of .m and .h files. That list of files is then piped to the xargs command, which will run the given sed command for each of those files. The sed command then scans for lines matching <retain type>, nonatomic, takes the retain type, and replaces the occurrence​ with nonatomic, <retain type>, injecting back the same retain type.

And that's all there's to it! While it may have taken us 15 minutes to figure out the proper command, at least we didn't spend the same amount of time manually editing those files like some chump. I call that a win.