rr – 1.0 – Now a Pipe Friendly Filter

rr has reached the 1.0 milestone! The obvious improvement over the last version is that input is allowed from standard input. It seemed silly to always require a filename and the option of having standard input was always on my to do list. Usage is now:

usage: rr [options] find replace [filename]
       rr [options] s/find/replace/ [filename]

Now you can use rr as a filter and happily make find replace changes by piping input into it or out of it! I already have a script that runs a file through 4 rr commands to produce much nicer and cleaner output. Wrap that up in a shell/ruby/perl script and you have a useful tool.

Enjoy. Again its all free!
rr – Current Version Download
rr – changelog.txt – Click Here

$ gem install regex_replace

rr – Updated to 0.9.1

rr now has some improvements, including a new style of usage. Both this new style and the original style usage are available to you.

rr [options] s/find/replace/ filename

The new s/find/replace/ syntax is still weak with respect to the forward slash character in either the find or replace, but works for everything else so far. Of course if you want to include any whitespace then you should wrap the entire argument in quotes. Also, because the strings are coming from the command line, if you want to have literal backslashes then use single quotes around your string so the shell doesn’t escape them itself before sending it to Ruby.

Another highlight is that all escape sequences should now work. That means your typical \n, \t, and all the obscure even including \a (system bell). Check out this example, you will hear two system bells once this has been run:

$ echo "aba" > in.1; rr a "\a" in.1; rm in.1

Also I was considering renaming to fr for “Find/Replace” however I am keeping rr. rr can be interpreted as “Run Regex” with the s/find/replace/ syntax, or “Regex Replace” for the normal 3 argument usage. If you like fr you can easily make an alias like so: Want to know how to always load the alias?

$ alias fr="rr"

So have fun, of course everything is free and available right here:
rr – Current Version Download
rr – changelog.txt – Click Here

rr – Regex Replace on a File – SotD

I was frustrated with regular expression find/replace programs that only did line processing. This was because often I had find/replace needs that spanned multiple lines. Programs like grep, ack (which I recently found and is really, really very awesome for searching code), and sed were easy enough to use for basic needs. But again, when it came to multiple line pattern matching both fell short of my needs.

My solution was to write my own script to parse an entire file as a single string and do my find/replace bidding. The cons being liberal use of memory and a few hundredths of a second longer then the usual find/replace algorithms seemed insignificant to the pros of a multi-line capable find/replace using a regular expression with the capability of using back references (like \1) to incorporate captured groups from the regex into the replacement text.

So, without further ado I present rr.

I am hopeful for some public criticism to help me bring rr up from its current version of 0.9 to a landmark 1.0. The ruby script weighs in at 100 lines but really under 50 are code and the rest is comments, whitespace, or the usage string. Speaking of usage, here is what it currently [v0.9.0] looks like:

usage: rr [options] find replace filename
  find     - a regular expression to be run on the entire file as one string
  replace  - replacement text, \1-\9 and \n are allowed
  filename - name of the input file to be parsed

options: --line or -l process line by line instead of all at once (not default) --case or -c makes the regular expression case sensitive (not default) --global or -g process all occurrences by default (this is already default)
negated options are done by adding 'not' or 'n' in switches like so: --notline or -nl
example usage: The following takes a file and doubles the last character on each line and turns the newlines into two newlines. rr "(.)\\n" "\\1\\1\\n\\n" file

More then likely this will undergo a lot of changes. A quick list of my current ideas include:

  1. If no filename is provided take input from STDIN. Multiple files can be handled by piping the `cat` of multiple files through rr.
  2. Better switch structure, although right now I don’t have any idea what that is

I’ll throw a test scenario at you. I had tabulated data in a file but each row was split across multiple lines. Now this wasn’t the only data in the file but I’ll present you with a simplier version here: [in.1]

Product A  12.99
Product B   1.99

Here you can see that I can’t just replace every other newline. What I want to actually do is replace newlines where there was a digit followed by a newline, some whitespace and another digit. I ran this through my script:

> rr "(\d)\n\s+(\d)" "\1  \2" in.1 > out.1

And I got the output I wanted: [out.1]

Product A  12.99  2001
Product B   1.99  1997

Even cleaner results can be seen by running a more advanced regex to remove the extra lines:

> rr "(\\d)\\n\\s+(\\d.*?\\n)(-+\\n)?" "\\1  \\2" in.1
Product A  12.99  2001
Product B   1.99  1997

So what are you waiting for? Download the script, add it to your bin directory, give it a test run, and tell me how you want it improved!

rr – Most Recent Version – Download