srep

Overview

srep (Search and REPlace) matches regular expressions in files and replaces them with a given string. Output is either: a unified diff sent to stdout (i.e. without modifying files) with -u; or the direct modification of the files with -m. If no flag is specified, -u is assumed, since it is non-destructive.

Producing patches has the following advantages:

  • One can inspect srep's diff output and check that it has only matched against what was expected.
  • One can edit or remove any incorrect / one-off changes manually.
  • If for any reason the changes turn out not to be correct, running patch with the -R ('reverse') switch backs out the changes from the data in question.

Download

The latest version of srep is part of my bin repository; download it directly from github.

Usage

The command-line arguments are as follows:

srep [-rvmnu] [-t <number of expression + replacements>] <regular expression 1> <replacement 1> [... <regular expression t> <replacement t>] <file 1> ... <file n>

The flags are as follows:

-rRecurse into (nested) directories.
-vCreate additional logging information (shows which files are being matched, how many replacements made etc) and send it to stderr.
-mModify files in situ (warning: it may be difficult or impossible to undo any changes made).
-nProduce ndiff output (useful for seeing intra-line changes).
-uProduce unified diff output (default).

Examples

Here's an example of using srep on a code base of C files. The following command executes srep on all .c and .h files in the current directory, and outputs a unified diff (-u) into the changes file.
find . -name "\\.[ch]$" | xargs srep -u Con_Func_Obj Con_Func_Seg > changes
A fragment of the changes file is as follows (the full unified diff can be found here)
--- ./VM.c Sun Oct  2 14:31:38 2005
+++ ./VM.c Sun Oct  2 14:31:38 2005
@@ -183,12 +183,12 @@
 Con_Obj * Con_VM_apply(Con_EC_Obj *ec, Con_Obj *func)
 {
     jmp_buf env;
-    Con_Func_Obj *func_seg;
+    Con_Func_Seg *func_seg;
     Con_Obj *return_obj;
 
     if ((func->seg_c_class != ec->vm->builtins[CON_BUILTIN_FUNC_CLASS]))
         return NULL;
-    func_seg = (Con_Func_Obj *) func;
+    func_seg = (Con_Func_Seg *) func;
     
     if (func_seg->pc_type == PC_TYPE_C_FUNCTION) {
         if (sigsetjmp(env, 0) == 0) {
Once I have verified that the changes that will be made are what I expect, I can then apply this diff in the normal fashion:
patch -p0 < changes