references:
convert
capitalize
assert 'Groovy' == 'groovy'.capitalize()
uncapitalize
assert 'groovy' == 'Groovy'.uncapitalize()
assert 'hello World' == 'Hello World'.uncapitalize()
assert 'hello world' == 'Hello World'.tokenize().collect { it.uncapitalize() }.join(' ')
toLowerCase
assert 'groovy' == 'GRoOvy'.toLowerCase()
toUpperCase
assert 'GROOVY' == 'gRoovy'.toUpperCase()
substring
string indexing
assert '123' == '1234567'[0..2]
assert '67' == '1234567'[-2..-1]
minus
assert 'Hello ' == 'Hello World'.minus( 'World' )
assert ' World' == 'Hello World'.minus( 'Hello' )
- or
assert 'Hello ' == 'Hello World' - 'World' assert ' World' == 'Hello World' - 'Hello'
take
assert 'G' == 'Groovy'.take(1)
assert 'Gr' == 'Groovy'.take(2)
assert 'Gro' == 'Groovy'.take(3)
takeRight
[!TIP] returns the last num elements from this CharSequence.
assert '' == 'Groovy'.takeRight( 0 )
assert 'y' == 'Groovy'.takeRight( 1 )
assert 'ovy' == 'Groovy'.takeRight( 3 )
takeAfter
assert ' development. Groovy team' == 'Groovy development. Groovy team'.takeAfter( 'Groovy' )
assert 'team' == 'Groovy development. Groovy team'.takeAfter( ' Groovy ' )
takeBefore
assert 'Groovy ' == 'Groovy development. Groovy team'.takeBefore( 'development' )
assert 'Groovy development' == 'Groovy development. Groovy team'.takeBefore( '. Groovy ' )
takeBetween
assert ' development. ' == 'Groovy development. Groovy team'.takeBetween( 'Groovy' )
assert 'marslo' == 'name = "marslo"'.takeBetween( '"' )
assert '10' == "t1='10' ms, t2='100' ms".takeBetween( "'" )
assert '10' == "t1='10' ms, t2='100' ms".takeBetween( "'", 0 )
assert '100' == "t1='10' ms, t2='100' ms".takeBetween( "'", 1 )
takeWhile
[!TIP] returns the longest prefix of this CharSequence where each element passed to the given closure evaluates to true.
assert '' == 'Groovy'.takeWhile{ it < 'A' }
assert 'G' == 'Groovy'.takeWhile{ it < 'a' }
assert 'Gr' == 'Groovy'.takeWhile{ it != 'o' }
drop
assert 'ovY' == 'GroovY'.drop(3)
assert '' == 'GroovY'.drop(10)
dropWhile
[!TIP] create a suffix of the given CharSequence by dropping as many characters as possible from the front of the original CharSequence such that calling the given closure condition evaluates to true when passed each of the dropped characters.
assert 'roovY' == 'GroovY'.dropWhile{ it < 'Z' }
tr
assert 'hEllO' == 'hello'.tr('aeiou', 'AEIOU')
assert 'HELLO' == 'hello'.tr('a-z', 'A-Z' )
// if replacementSet is smaller than sourceSet, then the last character from replacementSet is used as the replacement for all remaining source characters as shown here:
assert 'HAAAA WAAAA!' == 'Hello World!'.tr('a-z', 'A')
// if sourceSet contains repeated characters, the last specified replacement is used as shown here:
assert 'He224 W4r2d!' == 'Hello World!'.tr('lloo', '1234')
tricky
remove the last x chars
def removeSuffix( String str ) {
removeSuffix( str, 1 )
}
/**
* remove the last char of {@code str}
* @param str the string will be removal the last char
* @param c remove last {@code c} numbers chars
**/
def removeSuffix( String str, int c ) {
str.reverse().drop(c).reverse()
}
add char(s) in the end of string
str.concat('substr')
comparation
equalsIgnoreCase
assert true == "HELLO World".equalsIgnoreCase( 'hello world' )
compareToIgnoreCase
assert 0 == "Hello World".compareToIgnoreCase( 'hello world' )
repalce
reverse
assert '1234' == '4321'.reverse()
replaceAll
[!TIP] public String replaceAll(Pattern pattern, Closure closure)
- replaces all occurrences of a captured group by the result of a closure call on that text.
assert 'hellO wOrld' == 'hello world'.replaceAll(~"(o)") { it[0].toUpperCase() }
assert 'FOOBAR-FOOBAR-' == 'foobar-FooBar-'.replaceAll(~"(([fF][oO]{2})[bB]ar)", { it[0].toUpperCase() })
// Here,
// it[0] is the global string of the matched group
// it[1] is the first string in the matched group
// it[2] is the second string in the matched group
assert 'FOO-FOO-' == 'foobar-FooBar-'.replaceAll("(([fF][oO]{2})[bB]ar)", { x, y, z -> z.toUpperCase() })
// Here,
// x is the global string of the matched group
// y is the first string in the matched group
// z is the second string in the matched group
replaceFirst
[!TIP] public String replaceFirst(CharSequence regex, Closure closure))
- Replaces the first occurrence of a captured group by the result of a closure call on that text.
assert 'hellO world' == 'hello world'.replaceFirst("(o)") { it[0].toUpperCase() } // first match
assert 'hellO wOrld' == 'hello world'.replaceAll("(o)") { it[0].toUpperCase() } // all matches
assert '1-FISH, two fish' == 'one fish, two fish'.replaceFirst(/([a-z]{3})\s([a-z]{4})/) { [one:1, two:2][it[1]] + '-' + it[2].toUpperCase() }
assert '1-FISH, 2-FISH' == 'one fish, two fish'.replaceAll(/([a-z]{3})\s([a-z]{4})/) { [one:1, two:2][it[1]] + '-' + it[2].toUpperCase() }
replaceAll with case-insensitive
[!TIP|label:references:]
- How to replace case-insensitive literal substrings in Java
- Use replaceAll() to ignore case when replacing one substring with another
- Case insensitive String split() method
- useful libs:
- Class java.util.regex.Matcher
- Class java.util.regex.Pattern
- Special constructs (non-capturing) : Constant Field Values
- tutorial: Methods of the Pattern Class
- tutorial: Methods of the Matcher Class
EQUIVALENT EMBEDDED FLAG EXPRESSION | CONSTANT |
---|---|
None |
Pattern.CANON_EQ |
(?i) |
Pattern.CASE_INSENSITIVE |
(?x) |
Pattern.COMMENTS |
(?m) |
Pattern.MULTILINE |
(?s) |
Pattern.DOTALL |
None |
Pattern.LITERAL |
(?u) |
Pattern.UNICODE_CASE |
(?d) |
Pattern.UNIX_LINES |
String target = '++Apple@@Banana | aPPle##BanANa$$'
Map<String, String> p = [ 'banana' : '--', 'apple' : '==' ]
assert '++==@@-- | ==##--$$' == p.inject('') { injected, k, v ->
injected = ( injected ?: target ).replaceAll( "(?i)${k}", v );
injected
}
or
import java.util.regex.Pattern String parentPath = 'D:\\ifs\\APP\\Checkout' String path = 'D:\\IFS\\APP\\Checkout\\trvexp\\client\\Ifs.App\\text.txt' assert '\\trvexp\\client\\Ifs.App\\text.txt' == path.replaceAll( "(?i)" + Pattern.quote(parentPath), '' )
-
import java.util.regex.Pattern String label = 'table' String html = '<table>aaa</table>' assert '<WINDOWS>aaa</WINDOWS>' == Pattern.compile(label, Pattern.CASE_INSENSITIVE).matcher(html).replaceAll("WINDOWS");
Apply proper uppercase and lowercase on a String
import java.util.regex.Matcher
import java.util.regex.Pattern
String str = "this is a test"
StringBuffer sb = new StringBuffer()
Matcher m = Pattern.compile("([a-z])([a-z]*)", Pattern.CASE_INSENSITIVE).matcher(str)
while ( m.find() ) {
m.appendReplacement( sb, m.group(1).toUpperCase() + m.group(2).toLowerCase() )
}
assert 'This Is A Test' == m.appendTail(sb).toString()
split
split string by Capital Letters
[!NOTE|label:references:]
- Java: Split string when an uppercase letter is found
- Split String by Capital letters in Java
\p{Lu}
|\p{Upper}
: shorthand for\p{Uppercase Letter}
\p{Ll}
|\p{Lower}
: shorthand for\p{Lowercase Letter}
- Lookahead and Lookbehind Zero-Length Assertions
- Java split is eating my characters
- Regex split string but keep separators
- Class java.util.regex.Pattern: POSIX character classes (US-ASCII only)
\p{Lower}
: A lower-case alphabetic character:[a-z]
\p{Upper}
: An upper-case alphabetic character:[A-Z]
\p{ASCII}
: All ASCII:[\x00-\x7F]
\p{Alpha}
: An alphabetic character:[\p{Lower}\p{Upper}]
\p{Digit}
: A decimal digit:[0-9]
\p{Alnum}
: An alphanumeric character:[\p{Alpha}\p{Digit}]
\p{Punct}
: Punctuation: One of!"#$%&'()*+,-./:;<=>?@[\]^_
{|}~`\p{Graph}
: A visible character:[\p{Alnum}\p{Punct}]
\p{Print}
: A printable character:[\p{Graph}\x20]
\p{Blank}
: A space or a tab:[ \t]
\p{Cntrl}
: A control character:[\x00-\x1F\x7F]
\p{XDigit}
: A hexadecimal digit:[0-9a-fA-F]
\p{Space}
: A whitespace character:[ \t\n\x0B\f\r]
// split by Uppercase
'IWantToSplitThisString'.split("(?=\\p{Lu})")
'IWantToSplitThisString'.split("(?=\\p{Upper})")
// result: ['I', 'Want', 'To', 'Split', 'This', 'String']
// split by Lowercase
'iwANTtOsPLITtHISsTRING'.split("(?=\\p{Ll})")
'iwANTtOsPLITtHISsTRING'.split("(?=\\p{Lower})")
// result: ['i', 'wANT', 'tO', 'sPLIT', 'tHIS', 'sTRING']
-
assert ['this', 'Is', 'My', 'String'] == "thisIsMyString".split("(?=[A-Z])");
-
String splitCamelCase(String s) { return s.replaceAll( String.format("%s|%s|%s", "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])", "(?<=[A-Za-z])(?=[^A-Za-z])" ), " " ); } [ "lowercase", "Class", "MyClass", "HTML", "PDFLoader", "AString", "SimpleXMLParser", "GL11Version", "99Bottles", "May5", "BFG9000", ].each { test -> System.out.println("${test.padRight(16)}: [" + splitCamelCase(test) + "]"); }
- result
lowercase : [lowercase] Class : [Class] MyClass : [My Class] HTML : [HTML] PDFLoader : [PDF Loader] AString : [A String] SimpleXMLParser : [Simple XML Parser] GL11Version : [GL 11 Version] 99Bottles : [99 Bottles] May5 : [May 5] BFG9000 : [BFG 9000]
- result
split via patten
[!NOTE|label:expect:]
- original:
'h1:aaa:h2:bbb'
- expect:
'<h1>aaa</h1><h2>bbb</h2>'
via
inject
String title = 'h1:aaa:h2:bbb' String pattern = 'h\\d' title.trim().split(':') .inject([:]) { injected, str -> key = str.matches(pattern) ? str : key injected[key] = injected.getOrDefault(key, '') + ( ! str.matches(pattern) ? ":${str}" : '') injected } .collectEntries {[ (it.key), it.value.tokenize(':').join(':') ]} .collect { "<${it.key}>${it.value}</${it.key}>" } .join()
via
split
String title = 'h1:aaa:h2:bbb' title.trim() .split( "(?=h\\d:)" ) .collect{ it.tokenize(':') } .collectEntries{[ (it.first().trim()) : it.last().trim() ]} .collect{ "<${it.key}>${it.value}</${it.key}>" } .join()
trim
stripIndent()
"""
try{
do this
} finally {
do that
}
""".stripIndent()
==> output :
try{
do this
} finally {
do that
}
stripMargin()
"""try{
| do this
|} finally {
| do that
|}
""".stripMargin()
==> output :
try{
do this
} finally {
do that
}
- or
"""try{ * do this *} finally { * do that *} """.stripMargin( '*' )
output format
expand
assert 'Groovy Grails Griffon' == 'Groovy\tGrails\tGriffon'.expand()
assert 'Groovy Grails Griffon' == 'Groovy\tGrails\tGriffon'.expand(10)
unexpand
assert 'Groovy\tGrails\tGriffon' == 'Groovy Grails Griffon'.unexpand()
assert 'Groovy\tGrails\tGriffon' == 'Groovy Grails Griffon'.unexpand(10)
padRright
println 'world******'.padRight(15) + 'hello'
println 'world'.padRight(15) + 'hello'
// result
// world****** hello
// world hello
or
println 'world******'.padRight(15, '.') + 'hello' println 'world'.padRight(15, '.') + 'hello' // result // world******....hello // world..........hello
center
println " HEADER ".center(50, "-")
println "Number:".padRight(20) + "20"
println "Name:".padRight(20) + "John Doe"
println "Address:".padRight(20) + "34 Some Street, London"
println "Subscriber:".padRight(20) + "YES"
println "Expired:".padRight(20) + "NO"
// result
// --------------------- HEADER ---------------------
// Number: 20
// Name: John Doe
// Address: 34 Some Street, London
// Subscriber: YES
// Expired: NO
size
count
assert 2 == 'Hello world'.count('o')
assert 2 == 'Hello worlld'.count('ll')
size
assert 11 == 'Hello world'.size()
assert 11 == 'Hello world'.length()
random
[!TIP] check also in * imarslo : generate the random String
references:
NOTE:
shuffled()
supports for Groovy 3+
shuffled
('0'..'z').shuffled().take(10).join()
- for number and chars only
(('a'..'z')+('A'..'Z')+(0..9)).shuffled().take(10).join()
file
[!NOTE|label:references:]
- Class File
- Class FilenameUtils)
- Package java.nio.file
- Class Paths VS. Interface Path)
// https://stackoverflow.com/a/49019436/2940319 assert sun.nio.fs.UnixPath == java.nio.file.Paths.get( '/a/b/c/d.txt' ).getClass() java.nio.file.Path path = java.nio.file.Paths.get( '/a/b/c/d.txt' )
- Java Files - java.nio.file.Files Class
IO | NIO |
---|---|
File file = new File( 'c:/data' ) file.createNewFile() |
Path path = Paths.get( 'c:/data' ) Files.createFile(path) |
File file = new File( 'c:/data' ) file.mkdir() |
Path path = Paths.get( 'c:/data' ) Files.createDirectory(path) |
File file = new File( 'c:/data' ) file.mkdirs() |
Path path = Paths.get( 'c:/data' ) Files.createDirectories(path) |
File file = new File( 'c:/data' ) file.exists() |
Path path = Paths.get( 'c:/data' ) Files.exists(path) |
dirname
# via File assert '/a/b/c' == ( new File('/a/b/c/d.txt') ).getParentFile().toString() assert '/a/b/c' == ( new File('/a/b/c/d.txt') ).getParent() assert '/a/b/c' == ( new File('/a/b/c/d.txt') ).parent # via java.nio.file.Paths assert '/a/b/c' == java.nio.file.Paths.get( '/a/b/c/d.txt' ).getParent().toString() assert '/a/b/c' == jhava.nio.file.Paths.get( '/a/b/c/d.txt' ).parent.toString()
basename
# via File assert 'd.txt' == (new File('/a/b/c/d.txt')).getName() assert 'd.txt' == (new File('/a/b/c/d.txt')).name # via java.nio.file.Paths assert 'd.txt' == java.nio.file.Paths.get( '/a/b/c/d.txt' ).getFileName().toString() assert 'd.txt' == java.nio.file.Paths.get( '/a/b/c/d.txt' ).fileName.toString()
isDirectory || isFile
assert true == ( new File('/Users/marslo/.vimrc') ).isFile() assert false == ( new File('/Users/marslo/.vimrc') ).isDirectory()
StringTokenizer
[!NOTE|label:references:]
import java.util.StringTokenizer
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) { System.out.println(st.nextToken()); }
output
this is a test
equals
String[] result = "this is a test".split("\\s"); for (int x=0; x<result.length; x++) System.out.println(result[x]);