I have a file contains following lines of strings separated by "|",
C:\Temp\demo\AAA.dat | C:\test\input\AAA.dat
C:\Temp\build\BBB.bat | C:\test\java\BBB.bat
C:\Temp\test\CCC.xml | C:\Apps\ftp\CCC.xml
after I read each line, I hope to extract each string separated by "|",
ie, after i get 1st line,
I need to get both C:\Temp\demo\AAA.dat and C:\test\input\AAA.dat;
Pls help how to use ant to do it???
I use following code I can only get each line :
<loadfile property="filelist" srcfile="C:\Temp\file1.txt"/>
<target name="test" depends="chkInput" description="test">
<for param = "line" list="${filelist}" delimiter="${line.separator}">
<sequential>
<echo>#{line}</echo>
</sequential>
</for>
</target>
Not each substring separated by "|", pls help how to get each substring separated by "|"?
Once you have the line, you can use <propertyregex> to separate the two pieces.
<for param = "line" list="${filelist}" delimiter="${line.separator}">
<sequential>
<echo>#{line}</echo>
<var name="first.part" unset="true"/>
<var name="second.part" unset="true"/>
<propertyregex
property="first.part"
input="#{line}"
regex="^([^\s]*)"
select="\1"/>
<propertyregex
property="second.part"
input="#{line}"
regex="\|\s*([^\s]*).*$"
select="\1"/>
</sequential>
</for>
Note you have to use either the <var/> task to unset the property (or otherwise, you're not changing the property, or the new task to declare that property is local to the <sequential/> entity.
Related
I am basically trying to do the following thing in Ant (v1.9.4):
I have a list of fixed string like {a,b,c,d} --> First how should I declare this in Ant?
Then I have an input parameter such as ${mystring} and I want to check if the variable value is in my list. Which means in this example, if the variable value is equals to a or b or c or d.
If so return true else false (or 0 and 1 something like that).
Is there a simple way to do that?
Thanks,
Thiago
Use ant property task to declare your stringlist.
Use ant contains condition to check whether list contains a specific item.
Something like :
<project>
<!-- your stringlist -->
<property name="csvprop" value="foo,bar,foobar"/>
<!-- fail if 'foobaz' is missing -->
<fail message="foobaz not in List => [${csvprop}]">
<condition>
<not>
<contains string="${csvprop}" substring="foobaz"/>
</not>
</condition>
</fail>
</project>
Or wrap it in a macrodef for resuse :
<project>
<!-- your stringlist -->
<property name="csvprop" value="foo,bar,foobar"/>
<!-- create macrodef -->
<macrodef name="listcontains">
<attribute name="list"/>
<attribute name="item"/>
<sequential>
<fail message="#{item} not in List => [#{list}]">
<condition>
<not>
<contains string="${csvprop}" substring="foobaz"/>
</not>
</condition>
</fail>
</sequential>
</macrodef>
<!-- use macrodef -->
<listcontains item="foobaz" list="${csvprop}"/>
</project>
-- EDIT --
From ant manual condition :
If the condition holds true, the property value is set to true by default; otherwise, the property is not set. You can set the value to something other than the default by specifying the value attribute.
So simply use a condition to create a property that is either true or not set, f.e. combined with the new if/unless feature introduced with Ant 1.9.1 :
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<!-- your stringlist -->
<property name="csvprop" value="foo,bar,foobar"/>
<!-- create macrodef -->
<macrodef name="listcontains">
<attribute name="list"/>
<attribute name="item"/>
<sequential>
<condition property="itemfound">
<contains string="${csvprop}" substring="foobaz"/>
</condition>
<!-- echo as example only instead of
your real stuff -->
<echo if:true="${itemfound}">Item #{item} found => OK !!</echo>
<echo unless:true="${itemfound}">Warning => Item #{item} not found !!</echo>
</sequential>
</macrodef>
<!-- use macrodef -->
<listcontains item="foobaz" list="${csvprop}"/>
</project>
output :
[echo] Warning => Item foobaz not found !!
Note that you need the namespace declarations to activate the if/unless feature.
I have a bug in the following ant macrodef definition:
<macrodef name="xxx" description="does xxx">
<attribute name="attr1" default=""/>
<sequential>
<echo message="doing yyy"/>
<echo message="#{attr1}" file="${builddir}/zzz.xml"/>
<taskdef name="xmltask" classname="com.oopsconsultancy.xmltask.ant.XmlTask"/>
<xmltask report="true" source="${builddir}/zzz.xml">
<call path="spuds" target="process-spuds">
<param name="spud-kicker" path="#count"/>
</call>
</xmltask>
</sequential>
</macrodef>
When it tries to call the target of the call inside the xmltask, i get a null pointer exception.
What am I doing wrong?
The file zzz.xml contains (supposedly) well formed xml. It contains a top level tag called "spuds" with an attribute named count. I want to invoke the spud-kicker ant target on the spuds tag and pass the value of the count attribute to that task.
I'm trying to refactor an Ant buildfile with many similar targets into a buildfile that uses macros. This roughly is what it looks like:
<macrodef name="build-text">
<argument name="lang" />
<element name="file-list"/>
<sequential>
<property name="lang" value="#{lang}" />
<xslt style="my_stylesheet.xsl" destdir="build" basedir="src">
<!-- lots of params here -->
<file-list />
</xslt>
</sequential>
</macrodef>
<target name="buildTextDE">
<build-text lang="DE">
<file-list>
<mapper>
<mapper type="glob" from="Text1_${lang}.html" to="Text1_${lang}.fo"/>
<mapper type="glob" from="Text2_${lang}.html" to="Text2_${lang}.fo"/>
</mapper>
</file-list>
</build-text>
</target>
There is another task called buildTextEN that is nearly identical except for the lang attribute. In some cases, the file list differs however. Now how would I like to simplify the buildfile further by defining a "global" mapping list that contains the file lists for German and English, each file with the placeholder for the language. I would like to reference this global mapping where no special case is needed. How would I do that?
I use task to run a target for all values from the list, taken from one property.
<foreach list="val1,val2" delimiter="," target="my.target" param="param_name"/>
Now, I want to put those values to the separate properties file as there is a lot of them.
So the question is: how can I read multiple (don't know how many) properties (lines in file in fact) from the file into one property?
The property file should look like this:
val1
val2
anothervalue
foobar
And the output should be:
"val1,val2,anothervalue,foobar"
be put in one property.
You can achieve this using LineTokenizer filter with loadfile. For example:
<target name="t">
<loadfile property="data_range" srcFile="ls.txt">
<filterchain> <!-- this filter outputs lines delimited by "," -->
<tokenfilter delimoutput=","/>
</filterchain>
</loadfile>
<foreach list="${data_range}" param="line" delimiter="," target="print" />
</target>
<target name="print">
<echo>line [${line}]</echo> <!-- you can do anything here -->
</target>
I have a for loop like the following:
<property name="audi" value="germany" />
<property name="toyota" value="japan" />
<for list="audi,toyota" param="car">
<sequential>
<echo>#{#{car}}</echo>
</sequential>
</for>
As you can see, I'm trying to echo the value "germany" then "japan", but it doesn't - it displays #{#{car}}
Any suggestions on how to do it?
Found it...
#{#{car}}
needs to be:
${#{car}}