Celsius to Farenheit

El operador =~ permite hacer casamientos parciales. Retorna un objeto util.regex.Matcherlang/util.regex.Matcherutil/regex/Matcher.html:

generaciondecodigos@nereida:~/src/groovy/strings$ groovysh
Groovy Shell (1.6.5, JVM: 1.6.0_0)
Type 'help' or '\h' for help.
----------------------------------------------------------------------------------
groovy:000> ("New York, NY 10292" =~ /\d{5}/).class
===> class java.util.regex.Matcher
groovy:000> ("New York, NY 10292" =~ /\d{5}/)[0]
===> 10292
groovy:000> ("New York, NY" =~ /\d{5}/)[0]
ERROR java.lang.IndexOutOfBoundsException: index is out of range 0..-1 (index = 0)
        at groovysh_evaluate.run (groovysh_evaluate:2)
        ...
Como se ve, si no hay casamiento se produce un error, ya que el array está vacío. Es por tanto conveniente asegurarse que se ha producido casamiento:
groovy:000> m = ("New York, NY 10292" =~ /\d{5}/)
===> java.util.regex.Matcher[pattern=\d{5} region=0,18 lastmatch=]
groovy:000> if (m) { m[0] }
===> 10292
groovy:000> m = ("New York, NY" =~ /\d{5}/)
===> java.util.regex.Matcher[pattern=\d{5} region=0,12 lastmatch=]
groovy:000> if (m) { m[0] }
===> null
groovy:000> m = ("New York, NY" =~ /\d{5}/)
===> java.util.regex.Matcher[pattern=\d{5} region=0,12 lastmatch=]
groovy:000> m.find()
===> false
Si la expresión regular tiene paréntesis de captura en su interior se devuelve un array conteniendo lo que se ha capturado en los paréntesis:

groovy:000>  m = "foo car baz" =~ /(.)ar/
===> java.util.regex.Matcher[pattern=(.)ar region=0,11 lastmatch=]
groovy:000> m[0]
===> [car, c]
groovy:000> m[0][1]
===> c

Veamos un ejemplo de uso de expresiones regulares en Groovy. el siguiente programa traduce entre temperaturas en escala Celsius y Farenheit:

~/src/groovy/strings$ cat -n c2f.groovy 
 1  #!/opt/local/bin/groovy
 2  def re = '''(?ix) 
 3    ^                       # begin of string
 4    \\s*
 5    ([-+]?\\d+(?:\\.\\d*)?) # number
 6    \\s*
 7    ([cf])                  # type
 8    \\s*
 9    $                       # end of string
10  ''';  
11  
12  print "Enter a temperature (i.e. 32F, 100C): ";
13  
14  def stdin = new BufferedReader(new InputStreamReader(System.in))
15  stdin.eachLine{ input ->
16      def m = (input =~ re);
17  
18      if (m) {
19        def (num, type) = m[0][1..2]
20        if ((type == 'C') || (type == 'c')) {
21          celsius = num.toDouble()
22          farenheit = (celsius * 9/5)+32
23      }
24      else {
25        farenheit = num.toDouble()
26        celsius = (farenheit -32)*5/9;
27      }
28        printf "%.2f C = %.2f F\n", celsius, farenheit;
29      }                       // this message to System.err
30      else System.err.println "Expecting a temperature, so don't understand \"$input\""  
31  
32      print "Enter a temperature (i.e. 32F, 100C): ";
33  } // end eachLine loop

Ejecución:

~/src/groovy/strings$ groovy c2f
Enter a temperature (i.e. 32F, 100C): 32f
0,00 C = 32,00 F
Enter a temperature (i.e. 32F, 100C):    100c
100,00 C = 212,00 F
Enter a temperature (i.e. 32F, 100C): juan
Expecting a temperature, so don't understand "juan"
Enter a temperature (i.e. 32F, 100C): ~/src/groovy/strings$
La última vez hemos presionado CTRL-D (unix) para generar el final de fichero.

Casiano Rodríguez León
2010-04-30