ant task to split the given strings - ant

I need to split the strings from the given url and that to be stored in a property.
Eg: Url: projectname/qa/projectid/version
Properties need to be store:
Name=projectname
Mode=qa
Id=projectid
Version=version

Use builtin javascript engine (JDK >= 1.6.06) and ant script task :
<project>
<property name="url" value="projectname/qa/projectid/version"/>
<script language="javascript">
arr = project.getProperty('url').split('/');
project.setProperty('Name', arr[0]);
project.setProperty('Mode', arr[1]);
project.setProperty('Id', arr[2]);
project.setProperty('Version', arr[3]);
</script>
<echo>
$${Name} => ${Name}
$${Mode} => ${Mode}
$${Id} => ${Id}
$${Version} => ${Version}
</echo>
</project>
output :
[echo] ${Name} => projectname
[echo] ${Mode} => qa
[echo] ${Id} => projectid
[echo] ${Version} => version
Wrap it up in a macrodef or scriptdef for reuse (equivalent to writing a new ant task).
If you prefer using some ant addon instead of ant script task see Ant Flaka which has several possibilities for string manipulation, see manual and examples.
-- EDIT --
split works with regexp, f.e. :
<project>
<property name="url" value="Chico.Harpo.Groucho.Gummo.Zeppo"/>
<script language="javascript">
<![CDATA[
// won't work because special meaning of '.' as wildcard
// arr = project.getProperty('url').split('.');
// so either use
// masking as character class '[.]' or '\\.'
arr = project.getProperty('url').split('[.]');
for (i=0; i < arr.length; i++)
{
print(arr[i]);
}
]]>
</script>
</project>

Just to show an alternative to Rebse's script approach, here is a more long-winded way with regular expression. You could extract each property with a block like this:
<property name="url" value="projectname/qa/projectid/version"/>
<loadresource property="Name">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="(\w+)/(\w+)/(\w+)/(\w+)" replace="\1"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="Name: ${Name}"/>
To answer your question from the comments, here is an example of how you could use that approach to extract the pieces you require. I didn't say it was pretty...
<target name="test">
<property name="url" value="http://svn.abc.com/builds/abcd/qa/FACC790C-1480-49F7-80F6-B91B07E52DA9/v1.0.1/r5532/"/>
<echo message="url: ${url}"/>
<loadresource property="a">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="http://([^/]+)/([^/]+)/([^/]+)/(?:[^/]+)/([^/]+)/v([^/]+)/r([^/]+)/" replace="\1"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="a: ${a}"/>
<loadresource property="b">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="http://([^/]+)/([^/]+)/([^/]+)/(?:[^/]+)/([^/]+)/v([^/]+)/r([^/]+)/" replace="\2"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="b: ${b}"/>
<loadresource property="c">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="http://([^/]+)/([^/]+)/([^/]+)/(?:[^/]+)/([^/]+)/v([^/]+)/r([^/]+)/" replace="\3"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="c: ${c}"/>
<loadresource property="d">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="http://([^/]+)/([^/]+)/([^/]+)/(?:[^/]+)/([^/]+)/v([^/]+)/r([^/]+)/" replace="\4"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="d: ${d}"/>
<loadresource property="e">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="http://([^/]+)/([^/]+)/([^/]+)/(?:[^/]+)/([^/]+)/v([^/]+)/r([^/]+)/" replace="\5"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="e: ${e}"/>
<loadresource property="f">
<string value="${url}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="http://([^/]+)/([^/]+)/([^/]+)/(?:[^/]+)/([^/]+)/v([^/]+)/r([^/]+)/" replace="\6"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="f: ${f}"/>
</target>
Output:
test:
[echo] url: http://svn.abc.com/builds/abcd/qa/FACC790C-1480-49F7-80F6-B91B07E52DA9/v1.0.1/r5532/
[echo] a: svn.abc.com
[echo] b: builds
[echo] c: abcd
[echo] d: FACC790C-1480-49F7-80F6-B91B07E52DA9
[echo] e: 1.0.1
[echo] f: 5532
So in summary, reusing the same pattern each time, but selecting a different group (1-4). The pattern uses 6 capturing and 1 non-capturing group (for the /qa/ part). Lots of other ways you could do that.

Related

Resource Count in Ant Scripts

I just need to know how to modify the code below so that ant determines the number of lines in my text files (Please note all text files here will have same number of lines but that number is not fixed) and automatically executes them based on the loop.
<project name="ant-read-n-files" default="run" basedir=".">
<!-- Load the ant contrib lib -->
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<pathelement location="${basedir}/lib/ant-contrib.jar"/>
</classpath>
</taskdef>
<target name="read">
<!-- file a -->
<loadfile property="textFileA" srcfile="${basedir}/files/aaa.txt">
<filterchain>
<headfilter lines="1" skip="${linenum}"/>
</filterchain>
</loadfile>
<for param="line" list="${textFileA}" delimiter="${line.separator}">
<sequential>
<property name="textFileAValue" value="#{line}"/>
</sequential>
</for>
<!-- file b -->
<loadfile property="textFileB" srcfile="${basedir}/files/bbb.txt">
<filterchain>
<headfilter lines="1" skip="${linenum}"/>
</filterchain>
</loadfile>
<for param="line" list="${textFileB}" delimiter="${line.separator}">
<sequential>
<property name="textFileBValue" value="#{line}"/>
</sequential>
</for>
<!-- file c -->
<loadfile property="textFileC" srcfile="${basedir}/files/ccc.txt">
<filterchain>
<headfilter lines="1" skip="${linenum}"/>
</filterchain>
</loadfile>
<for param="line" list="${textFileC}" delimiter="${line.separator}">
<sequential>
<property name="textFileCValue" value="#{line}"/>
</sequential>
</for>
<!-- Print them all -->
<echo message="${textFileAValue}"/>
<echo message="${textFileBValue}"/>
<echo message="${textFileCValue}"/>
</target>
<target name="run">
<foreach param="linenum" list="0,1,2" target="read"/>
</target>
</project>
Here as you see list = "0,1,2" means the loop will verify first three lines of each text file, but i want this to be dynamic depending on the number of lines the files have.
Any help here would be greatly appreciated.
Thanks,
Ashley
The below solution works here:-
<project name="ant-read-n-files" default="run" basedir=".">
<!-- Load the ant contrib lib -->
<taskdef resource="net/sf/antcontrib/antlib.xml">
<classpath>
<pathelement location="${basedir}/lib/ant-contrib.jar"/>
</classpath>
</taskdef>
<target name="read">
<!-- file a -->
<loadfile property="textFileA" srcfile="${basedir}/files/aaa.txt">
<filterchain>
<headfilter lines="1" skip="${linenum}"/>
</filterchain>
</loadfile>
<for param="line" list="${textFileA}" delimiter="${line.separator}">
<sequential>
<property name="textFileAValue" value="#{line}"/>
</sequential>
</for>
<!-- file b -->
<loadfile property="textFileB" srcfile="${basedir}/files/bbb.txt">
<filterchain>
<headfilter lines="1" skip="${linenum}"/>
</filterchain>
</loadfile>
<for param="line" list="${textFileB}" delimiter="${line.separator}">
<sequential>
<property name="textFileBValue" value="#{line}"/>
</sequential>
</for>
<!-- file c -->
<loadfile property="textFileC" srcfile="${basedir}/files/ccc.txt">
<filterchain>
<headfilter lines="1" skip="${linenum}"/>
</filterchain>
</loadfile>
<for param="line" list="${textFileC}" delimiter="${line.separator}">
<sequential>
<property name="textFileCValue" value="#{line}"/>
</sequential>
</for>
<!-- Print them all -->
<echo message="${textFileAValue}"/>
<echo message="${textFileBValue}"/>
<echo message="${textFileCValue}"/>
</target>
<target name="run">
<!-- Get number of lines of one of the files -->
<loadfile property="textFile" srcfile="${basedir}/files/aaa.txt"/>
<resourcecount property="line.count" count="0" when="eq">
<tokens>
<concat>
<filterchain>
<tokenfilter>
<stringtokenizer delims="${line.separator}" />
</tokenfilter>
</filterchain>
<propertyresource name="textFile" />
</concat>
</tokens>
</resourcecount>
<echo message="Number of lines: ${line.count}" />
<script language="javascript">
var list="", n=parseInt(project.getProperty("line.count"), 0);
for (var i = 0; i < n; i++) list += i + ",";
project.setProperty("list", list);
</script>
<foreach param="linenum" list="${list}" target="read"/>
</target>
</project>

How to solve this ANT issue?

<loadfile property="UIfiles" srcfile="updated.txt">
<filterchain>
<linecontainsregexp>
<regexp pattern="ui/dev/"/>
</linecontainsregexp>
</filterchain>
</loadfile>
<echo file="Filelist.txt" append="true">${UIfiles}</echo>
I have the above code in build.xml file. updated.txt will contain some text like Projects/accounts/spec/ui/dev/dpdl/abc.xml. If this statement is present in the file, then the above code works as expected. If there is no match for regex "ui/dev" in updated.txt, ideally the value of UIfiles should be empty and should not write anything to Filelist.txt. But in my case "${UIfiles}" is getting appended in Filelist.txt. Please suggest how to avoid this. Thank you.
Works as expected. ${...} is the syntax for your property when not set, because
your file doesn't contain a line matching the regexp.
You need some if isset condition, with Ant 1.9.3 and new if unless feature :
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<loadfile property="UIfiles" srcfile="updated.txt">
<filterchain>
<linecontainsregexp>
<regexp pattern="ui/dev/"/>
</linecontainsregexp>
</filterchain>
</loadfile>
<echo file="Filelist.txt" append="true">${UIfiles} if:set="UIfiles"</echo>
</project>
otherwise for older Ant versions use:
<project>
<target name="checkfile">
<loadfile property="UIfiles" srcfile="updated.txt">
<filterchain>
<linecontainsregexp>
<regexp pattern="ui/dev/"/>
</linecontainsregexp>
</filterchain>
</loadfile>
</target>
<target name="appendfilelist" depends="checkfile" if="UIfiles">
<echo file="Filelist.txt" append="true">${UIfiles}</echo>
</target>
<project>

Retrieve all keys from properties file using Ant

I have a properties file containing key/value pairs:
key1=value1
key2=value2
...
How can I retrieve a list of all keys in this file using Ant?
Use loadfile with a filterchain, f.e. :
<project>
<!-- given some file with :
key=value
key=someothervalue
...
-->
<loadfile property="keysonly" srcfile="some.properties">
<filterchain>
<tokenfilter>
<replaceregex pattern="(.+)=.+" replace="\1"/>
</tokenfilter>
</filterchain>
</loadfile>
<echo>${keysonly}</echo>
</project>
If you need the keys in special form, f.e. comma separated use something like :
<loadfile property="keysonly" srcfile="some.properties">
<filterchain>
<tokenfilter>
<!-- use some delimiter f.e. '###' -->
<replaceregex pattern="(.+)=.+" replace="\1###"/>
</tokenfilter>
<!-- get rid of linefeeds -->
<striplinebreaks/>
<tokenfilter>
<!-- replace delimiter '###' with ',' -->
<replaceregex pattern="###" replace="," flags="g"/>
</tokenfilter>
<tokenfilter>
<!-- replace dangling ',' -->
<replaceregex pattern=",$" replace=""/>
</tokenfilter>
</filterchain>
</loadfile>

Ant: get multiple matches with propertyregex

I have these (sample) lines in a HTML-file:
test.ABC.test
test.ABCD.test
test.ABCE.test
And this Ant propertyregex:
<loadfile property="getRecords" srcFile="./index.html"/>
<propertyregex property="record" input="${getRecords}" regexp="test\.([^\.]*)\.test" select="\1" casesensitive="true" override="true" global="true" />
<echo message="${record}" />
The result is just
ABC
But I'd like to get all matches. How can I get
ABC
ABCD
ABCE
as result?
Not sure about the propertyregex problem, but this works (without ant-contrib):
<target name="test">
<loadfile property="record" srcFile="./index.html">
<filterchain>
<tokenfilter>
<containsregex pattern=".*test\.([^\.]*)\.test.*" replace="\1"/>
</tokenfilter>
</filterchain>
</loadfile>
<echo message="${record}" />
</target>

Pretty-printing comma-separated list of strings in ant

I have a comma-separated string in an ant property, like this:
<property name="prop" value="a,b,c"/>
I would like to be able to print or log it like this:
Line 1: a
Line 2: b
Line 3: c
Doesn't sound like it should be too difficult, but I cannot figure out which ant components I should be putting together.
You can do this by using loadresource specifying the property value as a string resource. Now you can use a replaceregex filter to convert comma to newline.
<project default="test">
<property name="prop" value="a,b,c"/>
<target name="test">
<loadresource property="prop.fmt">
<string value="${prop}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="," replace="${line.separator}" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="${prop.fmt}"/>
</target>
</project>
The output is:
test:
[echo] a
[echo] b
[echo] c
The sample using Ant-Contrib Tasks
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<target name="test_split">
<property name="prop" value="a,b,c"/>
<for list="${prop}" param="letter">
<sequential>
<echo>#{letter}</echo>
</sequential>
</for>
</target>
The output is:
a
b
c
Another solution from here:
<scriptdef name="split" language="javascript">
<attribute name="value"/>
<attribute name="delimiter"/>
<attribute name="prefix"/>
<![CDATA[
values = attributes.get("value").split(attributes.get("delimiter"));
for(i=0; i<values.length; i++) {
project.setNewProperty(attributes.get("prefix")+i, values[i]);
}
]]>
</scriptdef>
<target name="test_split2">
<property name="prop" value="a,b,c"/>
<property name="prefix_str" value="Line_"/>
<split value="${prop}" delimiter="," prefix="${prefix_str}"/>
<echoproperties prefix="${prefix_str}"/>
</target>
The output is:
Ant properties
Tue Nov 22 17:12:55 2011
Line_0=a
Line_1=b
Line_2=c

Resources