~$ groovy -h usage: groovy [options] [args] options: -a,--autosplit <splitPattern> split lines using splitPattern (default '\s') using implicit 'split' variable -c,--encoding <charset> specify the encoding of the files -D,--define <name=value> define a system property -d,--debug debug mode will print out full stack traces -e <script> specify a command line script -h,--help usage information -i <extension> modify files in place; create backup if extension is given (e.g. '.bak') -l <port> listen on a port and process inbound lines -n process files line by line using implicit 'line' variable -p process files line by line and print result (see also -n) -v,--version display the Groovy and JVM versions
Because looping through STDIN
or input files tends to be a common thing
to do, groovy (and ruby, perl etc) provide shortcuts for this.
-n
will loop through each line of the input, and provide it to your script in the line variable.
~/LGCbook$ grep -i ^groov /usr/share/dict/words | groovy -n -e 'println line.toUpperCase()' GROOVE GROOVELESS GROOVELIKE GROOVER GROOVERHEAD GROOVINESS GROOVING GROOVY
-p
and shorten it to
~/LGCbook$ grep -i ^groov /usr/share/dict/words | groovy -p -e 'line.toUpperCase()' GROOVE GROOVELESS GROOVELIKE GROOVER GROOVERHEAD GROOVINESS GROOVING GROOVY
-i
, which writes the
output back to the original files (and creates a backup copy with
the given extension). And wreak havoc on our local file system,
with wide-scale search and replace.
~/LGCbook$ grep hola gcexamples/*.html gcexamples/node65.html: 14 ph = p("hola ") gcexamples/node65.html:hola mundo gcexamples/node79.html:groovy:000> SomeClass.classField = 'hola' gcexamples/node79.html:===> hola gcexamples/node79.html:groovy:000> a.typedField = 'hola' gcexamples/node79.html:===> hola gcexamples/node80.html: String attr = 'hola' gcexamples/node80.html:hola ~/LGCbook$ groovy -p -i .bak -e '(line =~ "hola").replaceAll("hola CocaCola")' gcexamples/*.html ~/LGCbook$ grep hola gcexamples/*.html gcexamples/node65.html: 14 ph = p("hola CocaCola ") gcexamples/node65.html:hola CocaCola mundo gcexamples/node79.html:groovy:000> SomeClass.classField = 'hola CocaCola' gcexamples/node79.html:===> hola CocaCola gcexamples/node79.html:groovy:000> a.typedField = 'hola CocaCola' gcexamples/node79.html:===> hola CocaCola gcexamples/node80.html: String attr = 'hola CocaCola' gcexamples/node80.html:hola CocaCola
TIP: Never ever use the option -i
without a backup extension.
~/Lgroovy/files$ find . -name 'r*.groovy' ./readfile.groovy ./readline.groovy ~/Lgroovy/files$ find . -name 'r*.groovy' | xargs cat -n 1 #!/usr/bin/env groovy 2 // Reading a text file 3 file = args[0] 4 new File(file).eachLine{ line -> 5 println line 6 } 1 #!/usr/bin/env groovy 2 prompt = '\n> ' 3 print 'Enter text including a digit:' + prompt 4 System.in.eachLine{ line -> 5 // line is read from System.in 6 if (line =~ '\\d') println "Read: $line" // normal output to System.out 7 else System.err.println 'No digit found.' // this message to System.err 8 } ~/Lgroovy/files$ find . -name 'r*.groovy' | xargs groovy -i .bak -pe '(line =~ "//.*").replaceAll("")' ~/Lgroovy/files$ ls -l r*.groovy.bak -rw-r--r-- 1 casianorodriguezleon staff 111 15 abr 06:17 readfile.groovy.bak -rw-r--r-- 1 casianorodriguezleon staff 348 15 abr 06:16 readline.groovy.bak ~/Lgroovy/files$ diff ./readline.groovy ./readline.groovy.bak 5,7c5,7 < < if (line =~ '\\d') println "Read: $line" < else System.err.println 'No digit found.' --- > // line is read from System.in > if (line =~ '\\d') println "Read: $line" // normal output to System.out > else System.err.println 'No digit found.' // this message to System.err
count
. This can be used for a
number of convenient groovy one-liners.
Let us assume you want to prefix every line in a file with the line
number. Doing this requires next to no work in Groovy (we additionally
create a copy of the original file with the extension .bak
).
~/Lgroovy/files$ cat prueba one two three four ~/Lgroovy/files$ groovy -pi .bak -e "count + ': ' + line" prueba ~/Lgroovy/files$ cat prueba 1: one 2: two 3: three 4: four ~/Lgroovy/files$ cat prueba.bak one two three four
~/Lgroovy/files$ groovy -p -e "if (line =~ /groovy/) count + ': ' + line" *.groovy 4: def cli = new CliBuilder(usage: 'showdate.groovy -[chflms] [date] [prefix]') 24: // usage: showdate.groovy -[chflms] [date] [prefix] 1: #!/usr/bin/env groovy 2: //http://groovy.codehaus.org/gapi/groovy/util/CliBuilder.html 3: import groovy.util.CliBuilder 1: #!/usr/bin/env groovy 1: #!/usr/bin/env groovy 1: #!/usr/bin/env groovy 1: #!/usr/bin/env groovy 1: #!/usr/bin/env groovy 1: #!/usr/bin/env groovy
~/Lgroovy/files$ groovy -pe "if (count <=3) count+':'+line" tail.groovy ls.groovy 1:#!/usr/bin/env groovy 2:import java.lang.management.* 3: 1:#!/usr/bin/env groovy 2:if (args.length > 1) { 3: regexp = args[0]
-a
, which splits the current input
line into the array split
. By default the split pattern is " "
(one
space).
Print processes owned by root:
lhp@nereida:~$ ps aux | grep lhp root 16086 0.0 0.0 78748 3372 ? S<s 05:39 0:00 sshd: lhp [priv] lhp 16094 0.0 0.0 78852 1944 ? S< 05:39 0:00 sshd: lhp@pts/15 lhp 16170 0.0 0.1 22364 5192 pts/15 S<s 05:39 0:00 -bash root 16337 0.0 0.0 78748 3372 ? S<s 05:39 0:00 sshd: lhp [priv] lhp 16346 0.0 0.0 78748 1868 ? S< 05:39 0:00 sshd: lhp@pts/16 lhp 16425 0.0 0.1 22364 5156 pts/16 S<s 05:39 0:00 -bash lhp 22082 0.0 0.0 10444 1928 pts/15 S<+ 06:31 0:00 man paste lhp 22092 0.0 0.0 9672 1032 pts/15 S<+ 06:31 0:00 pager -s lhp 26079 0.0 0.0 15172 1136 pts/16 R<+ 07:13 0:00 ps aux lhp 26080 0.0 0.0 7544 924 pts/16 S<+ 07:13 0:00 grep lhp lhp@nereida:~$ ps aux | groovy -a -ne "if (split[0] =~ 'lhp') println split[-1]" lhp@pts/15 -bash lhp@pts/16 -bash paste -s aux split[-1]
-a
optionally takes another split pattern which
is then used instead.
Print all logins from /etc/passwd
that are not commented:
lhp@nereida:~$ groovy -a':' -ne 'if (split[0] =~ /^lh/) println split[0]' /etc/passwd lhp
~/Lgroovy/files$ cat accounts.txt 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 ~/Lgroovy/files$ groovy -a -pe "split[0].toInteger()+split[-2].toInteger()" accounts.txt 5 5 5 5
-l <port>
with a default port of 1960).
For each connection that is made to this port, groovy executes the supplied script on a line by line basis.
This oneliner will reverse every line that is thrown at it, try
telnet
to your machine on port 1960 to interact with this script.
lhp@nereida:~$ groovy -l -e "println line.reverse()" groovy is listening on port 1960 ^Clhp@nereida:~$ |
lhp@nereida:~/LGROOVYBook$ telnet localhost 1960 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hola aloh dabalearrozalazorraelabad dabalearrozalazorraelabad Connection closed by foreign host. lhp@nereida:~/LGROOVYBook$ |
-p
option from earlier, to automatically print the result of your script.
The following one liner is equivalent to the one liner immediately above.
groovy -l -p -e "line.reverse()"
Casiano Rodríguez León