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>
Related
I have 2 files:
Read.txt:
My name is=Joy
My age is=18
Write.txt:
Paste my name here:
Paste my age here:
So I should be able to read the name(Joy) and age(18) from Read.txt from the desired location(it will appear after '=') and write them into write.txt at the desired location(after ':') after a successful build. Do I need regex for this?
Can we do this using an Ant Script?
With invalid property names in your read.txt file, you'll have to do something a bit more complex.
Using the loadfile task, you can load the entire contents of the file and format it as necessary:
<target name="write-to-file">
<loadfile srcfile="read.txt" property="output">
<filterchain>
<tokenfilter>
<replacestring from="My name is=" to="Paste my name here:" />
<replacestring from="My age is=" to="Paste my age here:" />
</tokenfilter>
</filterchain>
</loadfile>
<echo file="write.txt" message="${output}" />
</target>
If you need to get the specific values for name and age (perhaps for use later in the script) you will have to load twice and filter the parts you need:
<target name="load-lines">
<loadfile srcfile="read.txt" property="my.name">
<filterchain>
<linecontains>
<contains value="My name is" />
</linecontains>
<tokenfilter>
<replacestring from="My name is=" to="" />
</tokenfilter>
</filterchain>
</loadfile>
<loadfile srcfile="read.txt" property="my.age">
<filterchain>
<linecontains>
<contains value="My age is" />
</linecontains>
<tokenfilter>
<replacestring from="My age is=" to="" />
</tokenfilter>
</filterchain>
</loadfile>
<echo file="write.txt" message="Paste my name here:${my.name}${line.separator}Paste my age here:${my.age}" />
</target>
<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>
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.
I am using following code block:
<copy tofile="${dir.report}\${file.report.name}.html" file="${dir.report}\${file.report.name}.html">
<filterchain>
<tokenfilter>
<replaceregex pattern="\[(script|apply)\]" replace="" />
</tokenfilter>
</filterchain>
</copy>
But replaceregex is not working
Can someone help me out here.
This would be a simpler solution:
<copy tofile="build/input1.html" file="src/input1.html">
<filterchain>
<tokenfilter>
<replacestring from="apply" to=""/>
<replacestring from="script" to=""/>
</tokenfilter>
</filterchain>
</copy>
The <copy> task cannot "self-copy" files. The source file path has to be different than the destination file path.
Luckily, the <replaceregexp> task provides a simpler solution:
<replaceregexp file="${dir.report}\${file.report.name}.html" flags="g">
<regexp pattern="\[(script|apply)\]"/>
<substitution expression=""/>
</replaceregexp>
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>