Groovy: Efficiency Oriented Programming
Lecture 3
Master Proteomics & Bioinformatics - University of Geneva
Alexandre Masselot - summer 2011
Contents

• Eclipse tips
• The Groovy truth
• Control structures
• Regular expressions, a few step forwards
• Introduction to classes
A couple of eclipse tips

• <ctrl>-F : search text in file, replace; regular expressions possible,
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,
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,
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)
A couple of linux (shell) tips

history to list the last console command
 history
 history | grep psql        //the last command with “psql”
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
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”
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
Control structures : the Groovy truth

• In many situations, a boolean (true or false) must be deduced from the
  context
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
Groovy truth   (cont’d)
Groovy truth                                                 (cont’d)

In Groovy, several condition produce false (and opposite produces true)
 assert   !false                  //boolean value
 assert   !(‘a’ =~ /b/)           //regular expression
 assert   ![]                     //empty list
 assert   ![:]                    //empty map
 assert   !‘‘                     //empty string
 assert   !0                      //zero
 assert   !null                   //null pointer

 assert   true
 assert   a=~/./
 assert   [1]
 assert   [a:1]
 assert   ‘my funny valentine’
 assert   1
 assert   new Object()
conditional construct

Like in perl, the classic if/else construction
 if(x<10){
   ...
 }else if(x<20){
   ...
 }else{
   ...
 }
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’
 }
Single line conditional statement

Like in other language, the (...)?(...):(...)
 boolean cond=true
 int x
 if(cond){ x=10 }
 else    { x=42 }
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
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 }
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
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']   ]
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”}
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)
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]
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]
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]
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’
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}
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 ..<
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}
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

• 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...).
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.
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.
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).
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/
regexp: find or match

Two operators are commonly used
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/
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.*/
regexp: anchoring
regexp: anchoring

When finding a pattern, we can anchor it
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/
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$/
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/
regexp: character classes

assert   ‘The Lord’ =~ /L.rd/   // . matches any character
assert   ‘The Lord’ =~ /L..d/
assert ! ‘The Lord’ =~ /.The/
regexp: character classes

assert   ‘The Lord’ =~ /L.rd/   // . matches any character
assert   ‘The Lord’ =~ /L..d/
assert ! ‘The Lord’ =~ /.The/
assert   ‘The Lord’ =~ /L[eoi]rd/ //character set
assert   ‘The Lord’ =~ /L[A-Za-z0-9]rd/
assert   ’12:23:56’ =~ /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/
regexp: character classes

assert   ‘The Lord’ =~ /L.rd/     // . matches any character
assert   ‘The Lord’ =~ /L..d/
assert ! ‘The Lord’ =~ /.The/
assert   ‘The Lord’ =~ /L[eoi]rd/ //character set
assert   ‘The Lord’ =~ /L[A-Za-z0-9]rd/
assert   ’12:23:56’ =~ /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/
assert   ‘12_;45’ ==~ /[^a-z]*/    //anything but [a-z]
regexp: character classes

assert   ‘The Lord’ =~ /L.rd/     // . matches any character
assert   ‘The Lord’ =~ /L..d/
assert ! ‘The Lord’ =~ /.The/
assert   ‘The Lord’ =~ /L[eoi]rd/ //character set
assert   ‘The Lord’ =~ /L[A-Za-z0-9]rd/
assert   ’12:23:56’ =~ /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/
assert   ‘12_;45’ ==~ /[^a-z]*/    //anything but [a-z]
assert   ‘1234’ ==~ /d+/        //any digit
assert ! ‘1234’ =~ /D/          //anything but digit
assert   ‘The_12_ring’ ==~ /w/ //word char [a-zA-Z0-9_]
assert ! ‘The_12_ring’ =~ /W/ //non-word char
assert   ‘of the Rings =~ /ofsth //space char [ trnf]
regexp: repetitions
regexp: repetitions

? : 0 or 1 matches
 ‘‘     ==~ /w?/
 ‘a‘    ==~ /w?/
 ‘aa’ ! ==~ /w?/
regexp: repetitions

? : 0 or 1 matches
 ‘‘     ==~ /w?/
 ‘a‘    ==~ /w?/
 ‘aa’ ! ==~ /w?/

* : zero or more
 ‘‘       ==~ /w*/
 ‘a‘      ==~ /w*/
 ‘aa‘     ==~ /w*/
regexp: repetitions

? : 0 or 1 matches
 ‘‘     ==~ /w?/
 ‘a‘    ==~ /w?/
 ‘aa’ ! ==~ /w?/

* : zero or more
 ‘‘       ==~ /w*/
 ‘a‘      ==~ /w*/
 ‘aa‘     ==~ /w*/

+ : one or more
 ‘‘   ! ==~ /w+/
 ‘a‘    ==~ /w+/
 ‘aa‘   ==~ /w+/
regexp: repetitions   (cont’d)
regexp: repetitions          (cont’d)

{n} : n times
 assert ‘abcd’ ==~ /w{4}/
regexp: repetitions             (cont’d)

{n} : n times
 assert ‘abcd’ ==~ /w{4}/

{n,m} : between n and m times
 assert ‘abcd’ ==~ /w{3,6}/
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,}/
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/
regexp: matching this or that
regexp: matching this or that

We can match “multiple choices”
 assert ‘this’ ==~ /this|that/
 assert ‘this’ ==~ /th(is|at)/
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/
regexp: modifiers

It is possible to modify the behavior of the matching engine
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/
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 .)
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).+/
regexp: looking around

Regular expression usually consume character
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
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
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])/
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)
 (?<=...)
regexp at works : splitting a string

One of the most commons use of the regular expression is to split a string
into an array
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’]
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’]
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}
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}
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>’]
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>"}
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>"}
regexp: capturing

Like in perl, it is possible to define with parenthesis sub patterns to be
captured in the pattern
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
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>"
                                }

groovy & grails - lecture 3

  • 1.
    Groovy: Efficiency OrientedProgramming 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 ofeclipse tips • <ctrl>-F : search text in file, replace; regular expressions possible,
  • 4.
    A couple ofeclipse 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 ofeclipse 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 ofeclipse 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 oflinux (shell) tips history to list the last console command history history | grep psql //the last command with “psql”
  • 8.
    A couple oflinux (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 oflinux (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 oflinux (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
  • 13.
    Groovy truth (cont’d)
  • 14.
    Groovy truth (cont’d) In Groovy, several condition produce false (and opposite produces true) assert !false //boolean value assert !(‘a’ =~ /b/) //regular expression assert ![] //empty list assert ![:] //empty map assert !‘‘ //empty string assert !0 //zero assert !null //null pointer assert true assert a=~/./ assert [1] assert [a:1] assert ‘my funny valentine’ assert 1 assert new Object()
  • 15.
    conditional construct Like inperl, the classic if/else construction if(x<10){ ... }else if(x<20){ ... }else{ ... }
  • 16.
    conditional construct Like inperl, 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 conditionalstatement Like in other language, the (...)?(...):(...) boolean cond=true int x if(cond){ x=10 } else { x=42 }
  • 18.
    Single line conditionalstatement 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 conditionalstatement 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 conditionalstatement 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 conditionalstatement (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 conditionalstatement (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 conditionalstatement (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) isevaluated 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) isevaluated 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 theflow (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 closuremakes 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 closuremakes 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 closuremakes 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 closuremakes 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 • Youwant to know if a string match a structure? find the matches? replace the matches? Regular expressions are the answer.
  • 32.
    Regular Expression • Youwant 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 • Youwant 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 • Youwant 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 • Youwant 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 • Youwant 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/
  • 37.
    regexp: find ormatch Two operators are commonly used
  • 38.
    regexp: find ormatch Two operators are commonly used The find operator: is a substring matching the pattern? assert “The Lord of the Rings” =~ /Lord/
  • 39.
    regexp: find ormatch 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.*/
  • 40.
  • 41.
    regexp: anchoring When findinga pattern, we can anchor it
  • 42.
    regexp: anchoring When findinga 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 findinga 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 findinga 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/
  • 46.
    regexp: character classes assert ‘The Lord’ =~ /L.rd/ // . matches any character assert ‘The Lord’ =~ /L..d/ assert ! ‘The Lord’ =~ /.The/ assert ‘The Lord’ =~ /L[eoi]rd/ //character set assert ‘The Lord’ =~ /L[A-Za-z0-9]rd/ assert ’12:23:56’ =~ /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/
  • 47.
    regexp: character classes assert ‘The Lord’ =~ /L.rd/ // . matches any character assert ‘The Lord’ =~ /L..d/ assert ! ‘The Lord’ =~ /.The/ assert ‘The Lord’ =~ /L[eoi]rd/ //character set assert ‘The Lord’ =~ /L[A-Za-z0-9]rd/ assert ’12:23:56’ =~ /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ assert ‘12_;45’ ==~ /[^a-z]*/ //anything but [a-z]
  • 48.
    regexp: character classes assert ‘The Lord’ =~ /L.rd/ // . matches any character assert ‘The Lord’ =~ /L..d/ assert ! ‘The Lord’ =~ /.The/ assert ‘The Lord’ =~ /L[eoi]rd/ //character set assert ‘The Lord’ =~ /L[A-Za-z0-9]rd/ assert ’12:23:56’ =~ /[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ assert ‘12_;45’ ==~ /[^a-z]*/ //anything but [a-z] assert ‘1234’ ==~ /d+/ //any digit assert ! ‘1234’ =~ /D/ //anything but digit assert ‘The_12_ring’ ==~ /w/ //word char [a-zA-Z0-9_] assert ! ‘The_12_ring’ =~ /W/ //non-word char assert ‘of the Rings =~ /ofsth //space char [ trnf]
  • 49.
  • 50.
    regexp: repetitions ? :0 or 1 matches ‘‘ ==~ /w?/ ‘a‘ ==~ /w?/ ‘aa’ ! ==~ /w?/
  • 51.
    regexp: repetitions ? :0 or 1 matches ‘‘ ==~ /w?/ ‘a‘ ==~ /w?/ ‘aa’ ! ==~ /w?/ * : zero or more ‘‘ ==~ /w*/ ‘a‘ ==~ /w*/ ‘aa‘ ==~ /w*/
  • 52.
    regexp: repetitions ? :0 or 1 matches ‘‘ ==~ /w?/ ‘a‘ ==~ /w?/ ‘aa’ ! ==~ /w?/ * : zero or more ‘‘ ==~ /w*/ ‘a‘ ==~ /w*/ ‘aa‘ ==~ /w*/ + : one or more ‘‘ ! ==~ /w+/ ‘a‘ ==~ /w+/ ‘aa‘ ==~ /w+/
  • 53.
  • 54.
    regexp: repetitions (cont’d) {n} : n times assert ‘abcd’ ==~ /w{4}/
  • 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/
  • 58.
  • 59.
    regexp: matching thisor that We can match “multiple choices” assert ‘this’ ==~ /this|that/ assert ‘this’ ==~ /th(is|at)/
  • 60.
    regexp: matching thisor 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/
  • 61.
    regexp: modifiers It ispossible to modify the behavior of the matching engine
  • 62.
    regexp: modifiers It ispossible 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 ispossible 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 ispossible 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).+/
  • 65.
    regexp: looking around Regularexpression usually consume character
  • 66.
    regexp: looking around Regularexpression usually consume character Let’s consider cleaving a protein sequence with trypsin ‘ACDEFKPGHRILKM’ =~/(w+?[KR])[^P]/ // the I is consumed
  • 67.
    regexp: looking around Regularexpression 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 Regularexpression 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 Regularexpression 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 acrossmatches 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 acrossmatches 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 acrossmatches 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 inperl, it is possible to define with parenthesis sub patterns to be captured in the pattern
  • 79.
    regexp: capturing Like inperl, 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 inperl, 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

  • #2 \n
  • #3 horizontal learning\n
  • #4 read the function shortcuts and try to memorize your most commons\n
  • #5 read the function shortcuts and try to memorize your most commons\n
  • #6 read the function shortcuts and try to memorize your most commons\n
  • #7 read the function shortcuts and try to memorize your most commons\n
  • #8 \n
  • #9 \n
  • #10 \n
  • #11 \n
  • #12 ask for perl before bullet 2\n
  • #13 ask for perl before bullet 2\n
  • #14 \n
  • #15 if you don&amp;#x2019;t write the break, next line will be evaluated!!\n
  • #16 if you don&amp;#x2019;t write the break, next line will be evaluated!!\n
  • #17 take care if params.x is 0 or &amp;#x2018;&amp;#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
  • #18 take care if params.x is 0 or &amp;#x2018;&amp;#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
  • #19 take care if params.x is 0 or &amp;#x2018;&amp;#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
  • #20 take care if params.x is 0 or &amp;#x2018;&amp;#x2019;\ndepends on the context\nparams.x?:42 + 23 != (params.x?:42) + 23\n
  • #21 \n
  • #22 \n
  • #23 \n
  • #24 \n
  • #25 sometimes, while(true) , then break exit for the condition\n
  • #26 sometimes, while(true) , then break exit for the condition\n
  • #27 \n
  • #28 rich scripting =&gt; TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
  • #29 rich scripting =&gt; TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
  • #30 rich scripting =&gt; TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
  • #31 rich scripting =&gt; TIMTOWTDI\nmore than one manner: choose your preferred, but be able to read other people code\n
  • #32 most of what is seen here was already discussed in winter =&gt; go fast\n
  • #33 most of what is seen here was already discussed in winter =&gt; go fast\n
  • #34 most of what is seen here was already discussed in winter =&gt; go fast\n
  • #35 most of what is seen here was already discussed in winter =&gt; go fast\n
  • #36 most of what is seen here was already discussed in winter =&gt; go fast\n
  • #37 most of what is seen here was already discussed in winter =&gt; go fast\n
  • #38 \n
  • #39 \n
  • #40 \n
  • #41 \n
  • #42 \n
  • #43 \n
  • #44 \n
  • #45 \n
  • #46 \n
  • #47 \n
  • #48 \n
  • #49 \n
  • #50 \n
  • #51 \n
  • #52 \n
  • #53 \n
  • #54 \n
  • #55 \n
  • #56 \n
  • #57 \n
  • #58 \n
  • #59 \n
  • #60 \n
  • #61 \n
  • #62 \n
  • #63 \n
  • #64 \n
  • #65 \n
  • #66 \n
  • #67 always prefer \\s+ to &amp;#x2018; &amp;#x2018; when you suspect tab\ninverse of split is join\n\n
  • #68 always prefer \\s+ to &amp;#x2018; &amp;#x2018; when you suspect tab\ninverse of split is join\n\n
  • #69 always prefer \\s+ to &amp;#x2018; &amp;#x2018; when you suspect tab\ninverse of split is join\n\n
  • #70 always prefer \\s+ to &amp;#x2018; &amp;#x2018; when you suspect tab\ninverse of split is join\n\n
  • #71 always prefer \\s+ to &amp;#x2018; &amp;#x2018; when you suspect tab\ninverse of split is join\n\n
  • #72 going through title for line length\n
  • #73 going through title for line length\n
  • #74 going through title for line length\n
  • #75 idem $1, $2 ... in perl\n
  • #76 idem $1, $2 ... in perl\n
  • #77 idem $1, $2 ... in perl\n