ruby -e for better console experience
Post image

This is a loose translation of my post from 2017.

Ruby was influenced by Perl and can substitute it in its niche of “practical extraction and reporting”. In this small post, I’ll talk about using ruby for simple text processing in the terminal.

TL;DR

Remember these two forms:

... | ruby -lne '<CODE>'
ruby -lne '<CODE>' file1, file2, ...

In the former, your input will come from some previous command output (via pipe). In the latter, it’ll come from the concatenation of multiple files.

CODE will be executed for every line of the input which will be available via $_ variable. Important: lines won’t have \n at the end (which is enabled via -l flag).

Examples

This is how we could implement tac (reverse cat):

ruby -lne 'puts $_.reverse' file-to-show.txt

Display the first 10 characters from each filename in the current directory:

ls | ruby -lne 'puts $_[0..9]'

Some details

Pre-defined variables

Ruby has many pre-defined variables which we may have never even heard of. Some of them coming from Perl, e.g. $_ and $< (to be precise, Perl doesn’t have $< but it’s got input operator <> reading from files/stdin and setting $_).

You can see the list of those variables here.

In the context of this post, I recommend you take a look at the aforementioned $_ and $< and also $~, $1, $stdin, ARGV, $stdout, STDIN и STDOUT.

gets’ terrible secret

Maybe you’ve used gets before to request some user input from the keyboard. However, what you may not know is that it also checks ARGV (command line arguments).

When ARGV isn’t empty gets assumes that it has a list of files, takes the first one and tries to read a line from it.

Consider this script:

# myscript.rb
puts gets

Let’s run it with ruby myscript.rb. As expected, the program is waiting for our input.

Let’s try running it with ruby myscript.rb no-such-file.txt

We’ll get a “no such file” error. Let’s change the script:

# myscript.rb
ARGV.pop
puts gets

Now the program is waiting for our input once again because we removed the item from ARGV.

Interpreter options

This is my template for one-liners:

ruby -lne <CODE> [file1, file2, ...]

(often without -l)

Here’s a description of used and some helpful options:

In conclusion

The first time I thought of using ruby-e because of the program cut. I had to use it a few times and every time I had to open the manual which my had was taking a long time to understand every time.

In the end, I thought: “Yes, I don’t know how to use cut=/=awk=/=sed. But I know quite a bit of Ruby so why can’t I just use it for small tasks?”.

So now, instead of remembering how to use numerous of **nix tools I can just remember this form:

ruby -lne CODE

And that’s it!

There’s nothing new about this approach. Bearded system administrators have been using perl for this for a long time.

P.S. Here’s an example of how I lately used this:

I downloaded a TV show but it had really ugly filenames like “s01e01 - super release by super-mega-macho.mkv”. I wanted to rename them to keep it neat. Here you go:

ls | ruby -lne 'File.rename($_, "#{$_[0..5]}.mkv")'