Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
groovy & grails - lecture 3
1. Groovy: Efficiency Oriented Programming
Lecture 3
Master Proteomics & Bioinformatics - University of Geneva
Alexandre Masselot - summer 2011
2. Contents
• Eclipse tips
• The Groovy truth
• Control structures
• Regular expressions, a few step forwards
• Introduction to classes
3. A couple of eclipse tips
• <ctrl>-F : search text in file, replace; regular expressions possible,
4. A couple of eclipse tips
• <ctrl>-F : search text in file, replace; regular expressions possible,
• <ctrl>-J + word : search text in file, without opening a popup,
5. A couple of eclipse tips
• <ctrl>-F : search text in file, replace; regular expressions possible,
• <ctrl>-J + word : search text in file, without opening a popup,
• <ctrl>-R + filena : jump to the given filename directly. If multiple files
correspond to the name entered, they are proposed,
6. A couple of eclipse tips
• <ctrl>-F : search text in file, replace; regular expressions possible,
• <ctrl>-J + word : search text in file, without opening a popup,
• <ctrl>-R + filena : jump to the given filename directly. If multiple files
correspond to the name entered, they are proposed,
• select text + <ctrl>-7 [ right button -> source -> toggle comment] :
passed the whole selection in or out comment mode (prepend // to lines)
7. A couple of linux (shell) tips
history to list the last console command
history
history | grep psql //the last command with “psql”
8. A couple of linux (shell) tips
history to list the last console command
history
history | grep psql //the last command with “psql”
<ctrl>-R to find last command
<ctrl>-r + ls //jump to last command with “ls”
//call <ctrl>-r multiple times
9. A couple of linux (shell) tips
history to list the last console command
history
history | grep psql //the last command with “psql”
<ctrl>-R to find last command
<ctrl>-r + ls //jump to last command with “ls”
//call <ctrl>-r multiple times
tab for completion of the current word in plenty of context
fin<tab> //all command start with “fin”
10. A couple of linux (shell) tips
history to list the last console command
history
history | grep psql //the last command with “psql”
<ctrl>-R to find last command
<ctrl>-r + ls //jump to last command with “ls”
//call <ctrl>-r multiple times
tab for completion of the current word in plenty of context
fin<tab> //all command start with “fin”
ls to list files
ls -lrt //long format, sorted reverse on time
ls -lh //size in human format (1.2M, 3.5G ...)
ls -lhrt | tail //10 most recent 10
11. Control structures : the Groovy truth
• In many situations, a boolean (true or false) must be deduced from the
context
12. Control structures : the Groovy truth
• In many situations, a boolean (true or false) must be deduced from the
context
• In perl, for example, false can be deduced from
• undef
• empty string ‘’
•0
16. conditional construct
Like in perl, the classic if/else construction
if(x<10){
...
}else if(x<20){
...
}else{
...
}
Or the switch
switch(x){
case 1 : println ‘one’; break
case 2..10 : println ‘between 2 and 10’; break
default : println ‘anything else’
}
17. Single line conditional statement
Like in other language, the (...)?(...):(...)
boolean cond=true
int x
if(cond){ x=10 }
else { x=42 }
18. Single line conditional statement
Like in other language, the (...)?(...):(...)
boolean cond=true
int x
if(cond){ x=10 }
else { x=42 }
Can be replaced by
int x=cond?10:42
19. Single line conditional statement
Like in other language, the (...)?(...):(...)
boolean cond=true
int x
if(cond){ x=10 }
else { x=42 }
Can be replaced by
int x=cond?10:42
In the same idea, a default value can be set
if(params.x){ xVal=params.x } else { xVal=42 }
20. Single line conditional statement
Like in other language, the (...)?(...):(...)
boolean cond=true
int x
if(cond){ x=10 }
else { x=42 }
Can be replaced by
int x=cond?10:42
In the same idea, a default value can be set
if(params.x){ xVal=params.x } else { xVal=42 }
Can be replaced with the ?: (the equivalent of perl’s ||)
xVal=params.x?:42
21. Single line conditional statement (cont’d)
Imagine we want to sort elements on last name, and if they are equals, on
the first name
def nameList=[[first:'Harry', last:'Potter'], [first:'Ron',
last:'Weasley'], [first:'Fred', last:'Weasley'], [first:'Georges', last:'Weasley'], , [first:'Hermione', last:'Granger'] ]
22. Single line conditional statement (cont’d)
Imagine we want to sort elements on last name, and if they are equals, on
the first name
def nameList=[[first:'Harry', last:'Potter'], [first:'Ron',
last:'Weasley'], [first:'Fred', last:'Weasley'], [first:'Georges', last:'Weasley'], , [first:'Hermione', last:'Granger'] ]
The first “long” way:
nameList.sort{o1, o2 ->
if(o1.last == o2.last){
return o1.first <=> o2.first // <=> the spaceship
}else{ // operator
return o1.last <=> o2.last // compares elements
}
}.each{println “$it.first $it.last”}
23. Single line conditional statement (cont’d)
Imagine we want to sort elements on last name, and if they are equals, on
the first name
def nameList=[[first:'Harry', last:'Potter'], [first:'Ron',
last:'Weasley'], [first:'Fred', last:'Weasley'], [first:'Georges', last:'Weasley'], , [first:'Hermione', last:'Granger'] ]
The first “long” way:
nameList.sort{o1, o2 ->
if(o1.last == o2.last){
return o1.first <=> o2.first // <=> the spaceship
}else{ // operator
return o1.last <=> o2.last // compares elements
}
}.each{println “$it.first $it.last”}
Or the more compact manner:
(o1.last <=> o2.last)?:(o1.first <=> o2.first)
24. While loop
while(cond) is evaluated until the condition is false
List l=[]
x=5
while(x--){
l << x
}
assert l == [4, 3, 2, 1, 0]
25. While loop
while(cond) is evaluated until the condition is false
List l=[]
x=5
while(x--){
l << x
}
assert l == [4, 3, 2, 1, 0]
A loop scope can be exited with a break
List l=[]
x=5
while(x--){
l << x
if(x==3) break // NB a single line statement, no {}
}
assert l == [4, 3]
26. Loop: breaking the flow (cont’d)
It can be useful to jump directly to the next iteration, without evaluation the
remaining part of the loop, with the continue statement
int x = 10
def list=[]
while(x--){
if (x%2) continue // return to the while evaluation
if (x<4) break // exit
list << x
}
assert list == [8, 6, 4]
27. for loop
Although closure makes it less critical, the for statement allows to walk
through a collection
String t=’’
for(String s in ‘a’..’d’){
t+=s
}
assert t == ‘abcd’
28. for loop
Although closure makes it less critical, the for statement allows to walk
through a collection
String t=’’
for(String s in ‘a’..’d’){
t+=s
}
assert t == ‘abcd’
It is equivalent to
(‘a’..’d’).each{t+=it}
29. for loop
Although closure makes it less critical, the for statement allows to walk
through a collection
String t=’’
for(String s in ‘a’..’d’){
t+=s
}
assert t == ‘abcd’
It is equivalent to
(‘a’..’d’).each{t+=it}
And
for(int i in 0..<5){println i} //NB the half inclusive ..<
30. for loop
Although closure makes it less critical, the for statement allows to walk
through a collection
String t=’’
for(String s in ‘a’..’d’){
t+=s
}
assert t == ‘abcd’
It is equivalent to
(‘a’..’d’).each{t+=it}
And
for(int i in 0..<5){println i} //NB the half inclusive ..<
is equivalent to
5.times{println it}
31. Regular Expression
• You want to know if a string match a structure? find the matches? replace
the matches? Regular expressions are the answer.
32. Regular Expression
• You want to know if a string match a structure? find the matches? replace
the matches? Regular expressions are the answer.
• Regular expression is a language by itself. Most of the features are cross
languages (perl, java, php...).
33. Regular Expression
• You want to know if a string match a structure? find the matches? replace
the matches? Regular expressions are the answer.
• Regular expression is a language by itself. Most of the features are cross
languages (perl, java, php...).
• TIMTOWTDI : regexp is a domain where syntax can become particularly
ugly, when inappropriate choice are made.
34. Regular Expression
• You want to know if a string match a structure? find the matches? replace
the matches? Regular expressions are the answer.
• Regular expression is a language by itself. Most of the features are cross
languages (perl, java, php...).
• TIMTOWTDI : regexp is a domain where syntax can become particularly
ugly, when inappropriate choice are made.
• A large toolkit is available, and we’ll try to present here the most commonly
used and groovy oriented syntax.
35. Regular Expression
• You want to know if a string match a structure? find the matches? replace
the matches? Regular expressions are the answer.
• Regular expression is a language by itself. Most of the features are cross
languages (perl, java, php...).
• TIMTOWTDI : regexp is a domain where syntax can become particularly
ugly, when inappropriate choice are made.
• A large toolkit is available, and we’ll try to present here the most commonly
used and groovy oriented syntax.
• “Mastering Regular Expressions” by Jeffrey E.L Friedl (O'Reilly).
36. Regular Expression
• You want to know if a string match a structure? find the matches? replace
the matches? Regular expressions are the answer.
• Regular expression is a language by itself. Most of the features are cross
languages (perl, java, php...).
• TIMTOWTDI : regexp is a domain where syntax can become particularly
ugly, when inappropriate choice are made.
• A large toolkit is available, and we’ll try to present here the most commonly
used and groovy oriented syntax.
• “Mastering Regular Expressions” by Jeffrey E.L Friedl (O'Reilly).
• http://www.regexp.info/
38. regexp: find or match
Two operators are commonly used
The find operator: is a substring matching the pattern?
assert “The Lord of the Rings” =~ /Lord/
39. regexp: find or match
Two operators are commonly used
The find operator: is a substring matching the pattern?
assert “The Lord of the Rings” =~ /Lord/
The match operator: is the whole string matching the pattern?
assert ! “The Lord of the Rings” ==~ /Lord/
assert “The Lord of the Rings” ==~ /.*Lord.*/
42. regexp: anchoring
When finding a pattern, we can anchor it
To the start of the line ^
assert ‘The Lord of the Rings’ =~ /^The Lord/
assert ! ‘The Lord of the Rings’ =~ /^Lord/
43. regexp: anchoring
When finding a pattern, we can anchor it
To the start of the line ^
assert ‘The Lord of the Rings’ =~ /^The Lord/
assert ! ‘The Lord of the Rings’ =~ /^Lord/
To the end of the line $
assert ‘The Lord of the Rings’ =~ /the Rings$/
assert ! ‘The Lord of the Rings’ =~ /Lord$/
44. regexp: anchoring
When finding a pattern, we can anchor it
To the start of the line ^
assert ‘The Lord of the Rings’ =~ /^The Lord/
assert ! ‘The Lord of the Rings’ =~ /^Lord/
To the end of the line $
assert ‘The Lord of the Rings’ =~ /the Rings$/
assert ! ‘The Lord of the Rings’ =~ /Lord$/
A word boundary b
assert ‘The Lord of the Rings’ =~ /bLor/
assert ‘The Lord of the Rings’ =~ /bThe Lor/
assert ‘The Lord of the Rings’ =~ /ordb/
45. regexp: character classes
assert ‘The Lord’ =~ /L.rd/ // . matches any character
assert ‘The Lord’ =~ /L..d/
assert ! ‘The Lord’ =~ /.The/
55. regexp: repetitions (cont’d)
{n} : n times
assert ‘abcd’ ==~ /w{4}/
{n,m} : between n and m times
assert ‘abcd’ ==~ /w{3,6}/
56. regexp: repetitions (cont’d)
{n} : n times
assert ‘abcd’ ==~ /w{4}/
{n,m} : between n and m times
assert ‘abcd’ ==~ /w{3,6}/
{n,} : ≥ n times
assert ‘abc’ ==~ /w{3,}/
57. regexp: repetitions (cont’d)
{n} : n times
assert ‘abcd’ ==~ /w{4}/
{n,m} : between n and m times
assert ‘abcd’ ==~ /w{3,6}/
{n,} : ≥ n times
assert ‘abc’ ==~ /w{3,}/
Greedy or not greedy ? Repetitions by default tries to consume the most
characters possible. Adding a question mark ‘?’ put the expanding operator
in restrictive mode
‘the Lord of the Rings’ =~ /.*s/
‘the Lord of the Rings’ =~ /.*?s/
59. regexp: matching this or that
We can match “multiple choices”
assert ‘this’ ==~ /this|that/
assert ‘this’ ==~ /th(is|at)/
60. regexp: matching this or that
We can match “multiple choices”
assert ‘this’ ==~ /this|that/
assert ‘this’ ==~ /th(is|at)/
Leftmost match: the order of the choice will infer the match
‘"So you're going to go through with it, then", Gandalf
the Wizard said slowly’ =~ /going|go/
‘"So you're going to go through with it, then", Gandalf
the Wizard said slowly’ =~ /go|going/
62. regexp: modifiers
It is possible to modify the behavior of the matching engine
Case sensitivity: by default, regular expression are case sensitive
assert ! ‘The Lord of the Rings’ =~ /ring/
assert ‘The Lord of the Rings’ =~ /(?i)ring/
63. regexp: modifiers
It is possible to modify the behavior of the matching engine
Case sensitivity: by default, regular expression are case sensitive
assert ! ‘The Lord of the Rings’ =~ /ring/
assert ‘The Lord of the Rings’ =~ /(?i)ring/
Multi or single line: by default, regular expression are not evaluated across
new line char (n are not covered by s or .)
64. regexp: modifiers
It is possible to modify the behavior of the matching engine
Case sensitivity: by default, regular expression are case sensitive
assert ! ‘The Lord of the Rings’ =~ /ring/
assert ‘The Lord of the Rings’ =~ /(?i)ring/
Multi or single line: by default, regular expression are not evaluated across
new line char (n are not covered by s or .)
In other word, with single line modifier, n is considered just like another
character
‘’’The Lord //NB ‘’’ for multi line string
of the Rings’’’ =~ /.+/
‘’’The Lord
of the Rings’’’ =~ /(?s).+/
66. regexp: looking around
Regular expression usually consume character
Let’s consider cleaving a protein sequence with trypsin
‘ACDEFKPGHRILKM’ =~/(w+?[KR])[^P]/ // the I is consumed
67. regexp: looking around
Regular expression usually consume character
Let’s consider cleaving a protein sequence with trypsin
‘ACDEFKPGHRILKM’ =~/(w+?[KR])[^P]/ // the I is consumed
If the next amino acid is consumed, it will not be caught in a situation where
we want to capture all the matches of the regular expression
68. regexp: looking around
Regular expression usually consume character
Let’s consider cleaving a protein sequence with trypsin
‘ACDEFKPGHRILKM’ =~/(w+?[KR])[^P]/ // the I is consumed
If the next amino acid is consumed, it will not be caught in a situation where
we want to capture all the matches of the regular expression
Hopefully, we can ‘lookahead’
‘ACDEFKPGHRILKM’ =~/(w+?[KR])(?=[^P])/
69. regexp: looking around
Regular expression usually consume character
Let’s consider cleaving a protein sequence with trypsin
‘ACDEFKPGHRILKM’ =~/(w+?[KR])[^P]/ // the I is consumed
If the next amino acid is consumed, it will not be caught in a situation where
we want to capture all the matches of the regular expression
Hopefully, we can ‘lookahead’
‘ACDEFKPGHRILKM’ =~/(w+?[KR])(?=[^P])/
Respectively, it is possible to check is a regexp matches before the captured
string (look behind)
(?<=...)
70. regexp at works : splitting a string
One of the most commons use of the regular expression is to split a string
into an array
71. regexp at works : splitting a string
One of the most commons use of the regular expression is to split a string
into an array
Splitting point can be defined by a regular expression
assert “a b c d”.split(/s+/)==[‘a’, ‘b’, ‘c’, ‘d’]
72. regexp at works : splitting a string
One of the most commons use of the regular expression is to split a string
into an array
Splitting point can be defined by a regular expression
assert “a b c d”.split(/s+/)==[‘a’, ‘b’, ‘c’, ‘d’]
An extra argument can be passed, to limit the number of elements in the
returned list
assert “a b c d”.split(/s+/, 3)==[‘a’, ‘b’, ‘c d’]
73. regexp at works : splitting a string
One of the most commons use of the regular expression is to split a string
into an array
Splitting point can be defined by a regular expression
assert “a b c d”.split(/s+/)==[‘a’, ‘b’, ‘c’, ‘d’]
An extra argument can be passed, to limit the number of elements in the
returned list
assert “a b c d”.split(/s+/, 3)==[‘a’, ‘b’, ‘c d’]
Do not forget to pipe to an collect closure
assert “0 1 2”.split(/s+/).collect{it as Integer}
74. regexp at works : splitting a string
One of the most commons use of the regular expression is to split a string
into an array
Splitting point can be defined by a regular expression
assert “a b c d”.split(/s+/)==[‘a’, ‘b’, ‘c’, ‘d’]
An extra argument can be passed, to limit the number of elements in the
returned list
assert “a b c d”.split(/s+/, 3)==[‘a’, ‘b’, ‘c d’]
Do not forget to pipe to an collect closure
assert “0 1 2”.split(/s+/).collect{it as Integer}
Or use splitEachLine
txt.splitEachLine(/regexp/){it.action}
75. regexp: loop across matches
All the occurrence of a match is returned into a list:
String title = "The Lord of the Rings"
assert (title=~/(?i)thes+w+/).collect{"<$it>"} ==
[‘<The Lord>’, ‘<the Rings>’]
76. regexp: loop across matches
All the occurrence of a match is returned into a list:
String title = "The Lord of the Rings"
assert (title=~/(?i)thes+w+/).collect{"<$it>"} ==
[‘<The Lord>’, ‘<the Rings>’]
It is also natural to loop across all such occurrences:
(title=~/(?i)thes+w+/).each{println "<$it>"}
77. regexp: loop across matches
All the occurrence of a match is returned into a list:
String title = "The Lord of the Rings"
assert (title=~/(?i)thes+w+/).collect{"<$it>"} ==
[‘<The Lord>’, ‘<the Rings>’]
It is also natural to loop across all such occurrences:
(title=~/(?i)thes+w+/).each{println "<$it>"}
Is equivalent to
title.eachMatch(/(?i)thes+w+/){println "<$it>"}
78. regexp: capturing
Like in perl, it is possible to define with parenthesis sub patterns to be
captured in the pattern
79. regexp: capturing
Like in perl, it is possible to define with parenthesis sub patterns to be
captured in the pattern
If such parenthesis are present, the java.util.regex.Matcher structure
returned is different
def matcher = title=~/(?i)thes+(w+)/
assert matcher.hasGroup()
assert matcher[0][0] == ‘The Lord’ //the whole match
assert matcher[0][1] == ‘Lord‘ //first captured block
80. regexp: capturing
Like in perl, it is possible to define with parenthesis sub patterns to be
captured in the pattern
If such parenthesis are present, the java.util.regex.Matcher structure
returned is different
def matcher = title=~/(?i)thes+(w+)/
assert matcher.hasGroup()
assert matcher[0][0] == ‘The Lord’ //the whole match
assert matcher[0][1] == ‘Lord‘ //first captured block
It is possible to loop around with a closure
(title=~/(?i)thes+(w+)/).each{all, name ->
println "all: <$all>, capt:<$name>"
}
Editor's Notes
\n
horizontal learning\n
read the function shortcuts and try to memorize your most commons\n
read the function shortcuts and try to memorize your most commons\n
read the function shortcuts and try to memorize your most commons\n
read the function shortcuts and try to memorize your most commons\n
\n
\n
\n
\n
ask for perl before bullet 2\n
ask for perl before bullet 2\n
\n
if you don&#x2019;t write the break, next line will be evaluated!!\n
if you don&#x2019;t write the break, next line will be evaluated!!\n
take care if params.x is 0 or &#x2018;&#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
take care if params.x is 0 or &#x2018;&#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
take care if params.x is 0 or &#x2018;&#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
take care if params.x is 0 or &#x2018;&#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
\n
\n
\n
\n
sometimes, while(true) , then break exit for the condition\n
sometimes, while(true) , then break exit for the condition\n
\n
rich scripting => TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
rich scripting => TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
rich scripting => TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
rich scripting => TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
most of what is seen here was already discussed in winter => go fast\n
most of what is seen here was already discussed in winter => go fast\n
most of what is seen here was already discussed in winter => go fast\n
most of what is seen here was already discussed in winter => go fast\n
most of what is seen here was already discussed in winter => go fast\n
most of what is seen here was already discussed in winter => go fast\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
always prefer \\s+ to &#x2018; &#x2018; when you suspect tab\ninverse of split is join\n\n
always prefer \\s+ to &#x2018; &#x2018; when you suspect tab\ninverse of split is join\n\n
always prefer \\s+ to &#x2018; &#x2018; when you suspect tab\ninverse of split is join\n\n
always prefer \\s+ to &#x2018; &#x2018; when you suspect tab\ninverse of split is join\n\n
always prefer \\s+ to &#x2018; &#x2018; when you suspect tab\ninverse of split is join\n\n