I'm getting an error as follows
Groovy script throws an exception of type class
java.util.regex.PatternSyntaxException with message =
Unexpected internal error near index 1
\
^
from the Split statement as follows:
String strClassPath = System.getProperty("java.class.path");
String[] path = strClassPath.split(System.getProperty("file.separator"));
How should I make this work correctly for both UNIX and Windows systems (that's why I'm using "file.separator")
Many thanks in advance
This calls java's split(String regexp). So your input must be a regexp (or must be quoted):
import java.util.regex.Pattern
def cp = {path, sep ->
path.split(Pattern.quote(sep))
}
assert cp('C:\\window\\something\\groovy.jar', '\\') == ['C:', 'window', 'something', 'groovy.jar']
assert cp('/usr/local/share/groovy.jar', '/') == ['', 'usr', 'local', 'share', 'groovy.jar']
So much for the regexp/split. If you are after the path, you might be better off using Path. e.g.
assert new File('/usr/local/share/groovy.jar').toPath().collect()*.toString() == ['usr', 'local', 'share', 'groovy.jar']
Related
I need to run a python script in windows system using groovy script.
Example:
python.exe c:/main.py argument1
I am new to groovy and I don't know, how to do it.
Please share me groovy syntax to run python as mentioned in the above example
I am preparing this script for jenkins.
so, "command".execute() is the right start.
But this command only starts a thread and you don't wait for the result.
try this code:
def task = "python main.py".execute()
task.waitFor()
println task.text
These lines start the execution, wait for it to finish and print the result.
To output already during execution for longer running tasks, I've written myself a small helper:
String.metaClass.executeCmd = { silent ->
//make sure that all paramters are interpreted through the cmd-shell
//TODO: make this also work with *nix
def p = "cmd /c ${delegate.value}".execute()
def result = [std: '', err: '']
def ready = false
Thread.start {
def reader = new BufferedReader(new InputStreamReader(p.in))
def line = ""
while ((line = reader.readLine()) != null) {
if (silent != false) {
println "" + line
}
result.std += line + "\n"
}
ready = true
reader.close()
}
p.waitForOrKill(30000)
def error = p.err.text
if (error.isEmpty()) {
return result
} else {
throw new RuntimeException("\n" + error)
}
}
This defines through meta programming a new method on String called executeCmd.
Put this on top of your file and then your line
"python c:/main.py".executeCmd()
This should show you all output during execution and it will help you to handle the paramaters the correcct way through the "cmd /c"-prefix. (If you just call execute on a string, you often run into problems with spaces and other characters in your command.
If you already have the parameters as a list and need some code which also runs on a *nix machine, try to call execute() on a list:
["python", "c:/main.py"].execute()
hope this helps
ps: http://mrhaki.blogspot.com/2009/10/groovy-goodness-executing-string-or.html
I am trying to parse an yaml file in Groovy. However I am facing issue while typecasting the result to Map object.
Here is my logic
import org.yaml.snakeyaml.Yaml
import java.util.Map
Reader reader = null
int tokenCount = 0
def Map map = null
StringTokenizer st = new java.util.StringTokenizer("Country.State.City", ".")
reader = new FileReader("filepath")
String val = null
Yaml yaml = new Yaml()
map = (Map) yaml.load(reader)
tokenCount = st.countTokens()
for (i=1; i < tokenCount; i++) {
String token = st.nextToken()
map = (Map) map.get(token)
}
val = map.get(st.nextToken()).toString()
However I am getting error at line:
map = (Map) map.get(token)
where it says:
"org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'some value' with class 'java.lang.String' to class 'java.util.Map' error at line: 15"..
Where I am going wrong?
your provided yaml file is syntactically incorrect. This is a fixed version:
location: C:\\Users\\amah11\\Desktop\\New folder
type: hi
Header:
Code:
Start: 0
End: 2
value: H00
Owner:
Start: 3
End: 5
value: AIM
User:
Start: 6
End: 8
Value: AIM
number: 1
Note that Code: **Static** in the original messes things up. And all the keys on the final level need a space after the : (e.g. Start:3 is wrong).
The actual error message is:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Static Start:0 End:2 value:H00' with class 'java.lang.String' to class 'java.util.Map'
which is rather clear in showing, that there is something wrong with the original file.
You might want to consider using an editor, that detects errors like this right away.
An alternative to the original code, would be the use of inject on the tokenizer:
def map = new Yaml().load(new FileReader("cardconfig.yml"))
println new StringTokenizer('Header.Code.End', '.').inject(map) { r, s -> r.get(s) }
BTW: you don't need to import java.util in groovy.
I am getting following error when i run groovy:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Users\kbekur\MuleStudio\workspace\GroovyTest\src\com\test\SQLGroovy.groovy: 3: unexpected token: # # line 3, column 2.
#Grab(group='org.hsqldb', module='hsqldb', version='2.3.2')
^
1 error
And my code is:
#Grapes([
#GrabConfig(systemClassLoader = true)
#Grab(group='org.hsqldb', module='hsqldb', version='2.3.2')
])
import groovy.sql.Sql
def db = [url:'jdbc:hsqldb:hsql://localhost/testdb', user:'sa', password:'', driver:'org.hsqldb.jdbc.JDBCDriver']
def sql = Sql.newInstance(db.url, db.user, db.password, db.driver)
println 'Some GR8 projects:'
sql.eachRow('select * from Persons') { row ->
println "${row.lastname.padRight(10)} ($row.personid)"
}
After analysis, I have found that
You can't annotate a statement.
You should put the grab annotation on an import, for instance.
I am not clear with above statement, what changes I need to make to fix compilation issue and load the jars.
I am referring the code from: jars, system class loader
You need a comma between the two items in the #Grapes list, ie:
#Grapes([
#GrabConfig(systemClassLoader = true),
#Grab(group='org.hsqldb', module='hsqldb', version='2.3.2')
])
You can also remove the #Grapes part, to give just:
#GrabConfig(systemClassLoader = true)
#Grab(group='org.hsqldb', module='hsqldb', version='2.3.2')
(no comma is needed here, as they are no longer in a List)
I am new to Groovy and I could not get around this issue. I appreciate any help.
I want to read a file from Groovy. While I am reading the content, for each line I want to substitute the string '${random_id}' and '${entryAuthor}' with different string values.
protected def doPost(String url, URL bodyFile, Map headers = new HashMap() ) {
StringBuffer sb = new StringBuffer()
def randomId = getRandomId()
bodyFile.eachLine { line ->
sb.append( line.replace("\u0024\u007Brandom_id\u007D", randomId)
.replace("\u0024\u007BentryAuthor\u007D", entryAuthor) )
sb.append("\n")
}
return doPost(url, sb.toString())
}
But I got the following error:
groovy.lang.MissingPropertyException:
No such property: random_id for class: tests.SimplePostTest
Possible solutions: randomId
at foo.test.framework.FooTest.doPost_closure1(FooTest.groovy:85)
at groovy.lang.Closure.call(Closure.java:411)
at groovy.lang.Closure.call(Closure.java:427)
at foo.test.framework.FooTest.doPost(FooTest.groovy:83)
at foo.test.framework.FooTest.doPost(FooTest.groovy:80)
at tests.SimplePostTest.Post & check Entry ID(SimplePostTest.groovy:42)
Why would it complain about a property, when I am not doing anything? I also tried "\$\{random_id\}", which works in Java String.replace(), but not in Groovy.
You are doing it the hard way. Just evaluate your file's contents with Groovy's SimpleTemplateEngine.
import groovy.text.SimpleTemplateEngine
def text = 'Dear "$firstname $lastname",\nSo nice to meet you in <% print city %>.\nSee you in ${month},\n${signed}'
def binding = ["firstname":"Sam", "lastname":"Pullara", "city":"San Francisco", "month":"December", "signed":"Groovy-Dev"]
def engine = new SimpleTemplateEngine()
template = engine.createTemplate(text).make(binding)
def result = 'Dear "Sam Pullara",\nSo nice to meet you in San Francisco.\nSee you in December,\nGroovy-Dev'
assert result == template.toString()
you better use groovy.text.SimpleTemplateEngine class; check this for more details http://groovy.codehaus.org/Groovy+Templates
The issue here is that Groovy Strings will evaluate "${x}" by substituting the value of 'x', and we don't want that behaviour in this case. The trick is to use single-quotes which denote plain old Java Strings.
Using a data file like this:
${random_id} 1 ${entryAuthor}
${random_id} 2 ${entryAuthor}
${random_id} 3 ${entryAuthor}
Consider this code, which is analogous to the original:
// spoof HTTP POST body
def bodyFile = new File("body.txt").getText()
StringBuffer sb = new StringBuffer()
def randomId = "257" // TODO: use getRandomId()
def entryAuthor = "Bruce Eckel"
// use ' here because we don't want Groovy Strings, which would try to
// evaluate e.g. ${random_id}
String randomIdToken = '${random_id}'
String entryAuthorToken = '${entryAuthor}'
bodyFile.eachLine { def line ->
sb.append( line.replace(randomIdToken, randomId)
.replace(entryAuthorToken, entryAuthor) )
sb.append("\n")
}
println sb.toString()
The output is:
257 1 Bruce Eckel
257 2 Bruce Eckel
257 3 Bruce Eckel
Hello I am using groovy 2.1.5 and I have to write a code which show the contens/files of a directory with a given path then it makes a backup of the file and replace a word/string from the file.
here is the code I have used to try to replace a word in the file selected
String contents = new File( '/geretd/resume.txt' ).getText( 'UTF-8' )
contents = contents.replaceAll( 'visa', 'viva' )
also here is my complete code if anyone would like to modify it in a more efficient way, I will appreciate it since I am learning.
def dir = new File('/geretd')
dir.eachFile {
if (it.isFile()) {
println it.canonicalPath
}
}
copy = { File src,File dest->
def input = src.newDataInputStream()
def output = dest.newDataOutputStream()
output << input
input.close()
output.close()
}
//File srcFile = new File(args[0])
//File destFile = new File(args[1])
File srcFile = new File('/geretd/resume.txt')
File destFile = new File('/geretd/resumebak.txt')
copy(srcFile,destFile)
x = " "
println x
def dire = new File('/geretd')
dir.eachFile {
if (it.isFile()) {
println it.canonicalPath
}
}
String contents = new File( '/geretd/resume.txt' ).getText( 'UTF-8' )
contents = contents.replaceAll( 'visa', 'viva' )
As with nearly everything Groovy, AntBuilder is the easiest route:
ant.replace(file: "myFile", token: "NEEDLE", value: "replacement")
As an alternative to loading the whole file into memory, you could do each line in turn
new File( 'destination.txt' ).withWriter { w ->
new File( 'source.txt' ).eachLine { line ->
w << line.replaceAll( 'World', 'World!!!' ) + System.getProperty("line.separator")
}
}
Of course this (and dmahapatro's answer) rely on the words you are replacing not spanning across lines
I use this code to replace port 8080 to ${port.http} directly in certain file:
def file = new File('deploy/tomcat/conf/server.xml')
def newConfig = file.text.replace('8080', '${port.http}')
file.text = newConfig
The first string reads a line of the file into variable. The second string performs a replace. The third string writes a variable into file.
Answers that use "File" objects are good and quick, but usually cause following error that of course can be avoided but at the cost of loosen security:
Scripts not permitted to use new java.io.File java.lang.String.
Administrators can decide whether to approve or reject this signature.
This solution avoids all problems presented above:
String filenew = readFile('dir/myfile.yml').replaceAll('xxx','YYY')
writeFile file:'dir/myfile2.yml', text: filenew
Refer this answer where patterns are replaced. The same principle can be used to replace strings.
Sample
def copyAndReplaceText(source, dest, Closure replaceText){
dest.write(replaceText(source.text))
}
def source = new File('source.txt') //Hello World
def dest = new File('dest.txt') //blank
copyAndReplaceText(source, dest) {
it.replaceAll('World', 'World!!!!!')
}
assert 'Hello World' == source.text
assert 'Hello World!!!!!' == dest.text
other simple solution would be following closure:
def replace = { File source, String toSearch, String replacement ->
source.write(source.text.replaceAll(toSearch, replacement))
}