I have a property which contained a string and now want to change it to be a comma separated list to test lines in a file.
Currently with one value the following works:
<loadfile property="contents" srcFile="output.log">
<filterchain>
<linecontains>
<contains value="${findvalue}"></contains>
</linecontains>
</filterchain>
</loadfile>
So if a line in a file contains:
Hello World!
And value of findvalue = 'World' it would find the line. Now we want to find all lines that may match multiple words. So if lines of a file contain:
Hello World!
Bye Everyone!
We want to set the property findvalue = World,Everyone and pickup both lines of the file. Hopefully I am making sense on this, little hard for me to fully explain. Any ideas on how to best accomplish this?
One way is to use a linecontainsregexp filter to get lines that match a certain regular expression. The trick is to convert the comma-separated list of values into a single regex.
If the property findvalue is World,Everyone, the regex could simply be World|Everyone, which means the line contains either World or Everyone.
<property name="findvalue" value="World,Everyone" />
<loadresource property="findvalueRegex">
<propertyresource name="findvalue"/>
<filterchain>
<tokenfilter>
<filetokenizer/>
<replacestring from="," to="|" />
</tokenfilter>
</filterchain>
</loadresource>
Then pass the findvalueRegex property containing this regex to the linecontainsregexp filter:
<loadfile property="contents" srcFile="output.log">
<filterchain>
<linecontainsregexp>
<regexp pattern="${findvalueRegex}" />
</linecontainsregexp>
</filterchain>
</loadfile>
linecontains takes multiple contains.
<loadfile property="contents" srcFile="output.log">
<filterchain>
<linecontains>
<contains value="${findvalue1}"/>
<contains value="${findvalue2}"/>
.
.
.. and so on..
</linecontains>
</filterchain>
</loadfile>
This would be helpful only when you have a defined list of tokens to be searched and you don't want them to be fetched dynamically.
I know it's too late to answer but it might help someone else like me. :)
Related
I have an ant property ${src.dirs} that contains a list of dirs separated by a semi colon.
Now i need to specify fileset (for replaceregexp) and that fileset has to contain all java files from all dirs listed in ${src.dirs}.
How can i do it (I don't use any ant-contrib funcky stuff, I use plain vanilla ant).
The src.dirs have this form: /usr/work/dir1/src;/usr/work/java/dir2/src;/usr/libabc/src
There's is an example on how to use propertyregex, but when I try to use it I get this error:
build.xml:98: Problem: failed to create task or type propertyregex
Edit:
Here's what was my final solution:
<loadresource property="source.dir.javafiles">
<propertyresource name="source.dir"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="\s*([;,]\s*)*$" replace="/**/*.java"/>
<replaceregex pattern="\s*([;,]\s*)+" replace="/**/*.java," flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<fileset dir="" includes="${source.dir.javafiles}"/>
These regexes ensure that trailing commas or semicolons don't produce wrong fileselectors.
You might be able to do this without using ant-contrib. Here's a possibility:
<property
name="dirlist"
value="/usr/work/dir1/src;/usr/work/java/dir2/src;/usr/libabc/src" />
<property name="file.wildcard" value="*.java" />
<loadresource property="dirs.include">
<propertyresource name="dirlist"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="^/" replace="" />
<replaceregex pattern=";/" replace="/**/${file.wildcard}," flags="g"/>
<replaceregex pattern="$" replace="/**/${file.wildcard}" />
</tokenfilter>
</filterchain>
</loadresource>
<fileset id="files" dir="/" includes="${dirs.include}" />
The work is split into two: first string processing to convert the semicolon-separated list into patterns suitable for use in a fileset includes attribute; second make a fileset from the pattern.
The loadresource task here is simply being used as a wrapper around a sequence of simple regular expression replacements. The three replacements deal with the leading root directory \, expanding the intra-string semicolons into Ant patterns and commas (which are used in includes attributes to separate entries), and adding a pattern at the end of the string.
In your case you might consider tuning this to not use the root directory in the dir attribute of the fileset.
propertyregex is from ant-contrib, which is why the example is not working for you.
Here is one way to achieve what you want.
<pathconvert property="src.dirs.includes" pathsep="/**/*.java,">
<path path="${src.dirs}" />
</pathconvert>
<replaceregexp match="\s+" replace=" " flags="g" byline="true">
<files id="files" includes="${src.dirs.includes}/**/*.java" />
</replaceregexp>
However spaces in any of the filenames (including their path) will stuff you up.
Do you simply have to go through these directories and do your compile, or must these directories be compiled together because of dependencies?
If there are no dependencies, you could try the <for/> task in Ant-Contrib. This lets you loop through a list like the one you have:
<for list="${src.dirs}"
param="my.src.dir"
delimiter=";">
<sequential>
<javac destdir="${javac.destdir}"
srcdir="#{my.src.dir}"
classpathref="main.classpath"/>
</sequential>
</for>
Of course, you might have to munge things for your correct destdir. You may find the <var/> task convenient when you use the <for/> task. The <var/> task allows you to reset variable names. When you repeat the <sequential/> set of tasks, you may find you want to reset certain properties.
By the way, if you have Ant 1.8 or higher, you can use the <local/> task instead of <var/>.
How do I convert Java class names into file paths using Ant tasks?
For example, given a property containing foo.bar.Duck I'd like to get out foo/bar/Duck.class.
I tried (and failed) to implement this in terms of <pathconvert> and <regexpmapper>.
Here's a possible way to do this:
<property name="class.name" value="foo.bar.Duck"/>
<loadresource property="file.name">
<string value="${class.name}" />
<filterchain>
<replaceregex pattern="\." replace="/" flags="g" />
<replaceregex pattern="$" replace=".class" />
</filterchain>
</loadresource>
This puts the desired foo/bar/Duck.class into the file.name property.
Here's another way, using Ant resources and an unpackagemapper, which is designed for this purpose. The opposite package mapper is also available.
<property name="class.name" value="foo.bar.Duck"/>
<resources id="file.name">
<mappedresources>
<string value="${class.name}" />
<unpackagemapper from="*" to="*.class" />
</mappedresources>
</resources>
You use the resource value by means of the property helper syntax ${toString:...}, e.g.:
<echo message="File: ${toString:file.name}" />
Yields
[echo] File: foo/bar/Duck.class
I feel using ant script-javascript for this is much simpler
<property name="class.name" value="foo.bar.duck" />
<script language="javascript">
var className = project.getProperty("class.name");
println("before: " + className);
var filePath= className.replace("\\", "/");
println("File Path: "+filePath);
project.setProperty("filePath", filePath);
</script>
<echo message="${filePath}" />
note: that naming your variable same as argument e.g var wsPath may give error, it gave to me!
courtesy: https://stackoverflow.com/a/16099717/4979331
I have files that I need cleaned up during the build process. There is a fixed string that I need removed everywhere it appears. The files are being copied so during that copy I tried including a filterset where the token is the text to be removed and the value is the empty string. This didn't work because I set begintoken and endtoken to the empty string and Ant didn't like that.
This is not a one time operation so it needs to be part of the build process. The files contain SQL INSERT statements and are used to populate tables at runtime. Each line references the schema plus the table name and I need just the table name, e.g.
insert into Schema1.Table1 ...
should be
insert into Table1 ...
Thank you!
Use a nested filterchain with tokenfilter, something like =
<copy todir="...">
<fileset dir="..." />
<filterchain>
<tokenfilter>
<replacestring from="Schema1." to="" />
</tokenfilter>
</filterchain>
</copy>
if you need regexp for replacement use =
...
<tokenfilter>
<replaceregex pattern="..." replace="..." flags="".../>
</tokenfilter>
...
instead.
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>
E.g. to trim the first n characters of the lines, so that
123
1234
becomes
3
34
?
<target name="test">
<property name="trim_count" value="2"/>
<copy file="c:/test.txt" tofile="c:/test2.txt" overwrite="true">
<filterchain>
<tokenfilter>
<linetokenizer/>
<replaceregex pattern="^.{1,${trim_count}}(.*)" replace="\1"/>
</tokenfilter>
<ignoreblank/>
</filterchain>
</copy>
</target>
I think you need to write a java class to accomplish that.
I don't think Ant supports this type of functionality by default. Instead you'd have to use an external utility. If you share some specifics of the OS you are using, as well as what kind of characters or pattern that you are attempting to remove we might be able to further aid you.