TIL: Using the Groovy CLI like Perl/AWK/...

While most of the time using groovysh as a REPL or groovyc to quickly compile a few files, I never realised that groovy comes with several features mimicking features from classic CLI tools like Perl.

The scripts to run on the input can either be passed as -e <s> where <s> is an argument with the actual Groovy code - or just pass a file name to load as script.

Filter lines like Perl

It's easy to write single line filters. The same works with groovy -ne 'script...'. The script gets line (the full line) and count (the current line number starting at 1). E.g.:

# head -n3 /etc/passwd | groovy -ne 'println "${count}. ${line}"'
1. root:x:0:0:root:/root:/bin/bash
2. daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3. bin:x:2:2:bin:/bin:/usr/sbin/nologin

There is also an option -a <s> to split the lines. If <s> is not given, a space is used. The array will be available as split in the script. E.g.:

# head -n3 /etc/passwd | groovy -n -a : -e 'println "${split[4]} uses ${split[6]}"'
root uses /bin/bash
daemon uses /usr/sbin/nologin
bin uses /usr/sbin/nologin

Begin and end AWK like

If the script to run contains a method begin and/or end, then those will be called at the beginning or end of processing. E.g.:

// stuff.groovy
def begin() {
    println "Start"
}

def end() {
    println "End"
}

println line
# head -n1 /etc/passwd | groovy -n stuff.groovy
Start
root:x:0:0:root:/root:/bin/bash
End

Transforming file content SED like

Given the flag -i <.suffix>, any arguments passed as files will be processed by the given script (and a <file.suffix> backup is stored. E.g.:

# echo World > 1.txt                               
# groovy -i .bak -p -e 'println "Hello ${line}"' 1.txt
# cat 1.txt                                           
Hello World
# cat 1.txt.bak 
World

Process data from sockets

Given the flag -l <port>, a socket server will be spawned and will run the given script against the data send from clients. E.g. start the server:

# groovy -l 5000 -e 'println "Hello, ${line}"'
groovy is listening on port 5000

And then send data to it:

# echo "World" | nc -w 1 localhost 5000
Hello, World