tags:

views:

219

answers:

1

Working with Ant's regular expressions system seems to give me no end of trouble. With enough work I can usually get it to work (and understand what I was doing wrong earlier). But not this time. I have a simple target wherein I want to extract the first element out of a property that contains one or more comma separated words, like this:

tgt.list.full=word1,word2,word3,word4

(Edit: tgt.list.full is actually populated by another property: tgt.list.basic, so the actual cfg.list.file looks like this:

tgt.list.basic=word1,word2,word3,word4
tgt.list.full=${tgt.list.basic}

)

I want the first word: "word1" to replace the ${target} property. This is what my task looks like:

 <target name="load-configuration-list">
     <loadproperties srcfile="${cfg.list.file}">
         <filterchain>
             <containsregex pattern="^tgt.list.full=(.*),?.*" replace="target=\1" />
             <concatfilter prepend="${cfg.list.file}" />
         </filterchain>
     </loadproperties>
     <echo message="TGT: ${target}, FULL: ${tgt.list.full}"/>
     <fail unless="target" message="A target cannot be determined"/>
 </target>

With the current version I have listed under the "containsregex" task, ${target} gets populated with the full list ("word1,word2,word3,word4") and not simply "word1." I have tried a large number of variations o the them. Here's an example:

<containsregex pattern="^tgt.list.full=(word1),?.*" replace="target=\1" />

I would expect that this would at least FORCE the target property to be populated, but in this case, ${target} remains undefined (not even the full list is put into it).

Perhaps there is a flaw in my filterchain logic. I know I could probably write task of my own, but Ant seems to have the components already that I need, if I can understand them better.

To rephrase my original question: given a comma separated list in an Ant property, how might I use an Ant task (not necessarily even using containsregex or replaceregex) to extract the first element?

+1  A: 

Would this regex be better suited to what you need ?

^tgt.list.full=([^,]+),?.*
^tgt.list.full=([^,]+),?[^\r\n]*$

Since '.' (dot) represents any character, '(.*),?.*' does select word1,word2,... because of the greediness of the * quantifier.
May be '(.*?),?.*' would have been better, but at least with [^,]+, we know a greedy operator will not capture any ','.

The second form may be needed to be sure to capture only what is on one line, and not "everything that follows a ," (including the next lines, since '.' in a 'dotall' mode, can include crlf characters).


As mentioned by Adam in the comments:

The "target" prop was actually being populated by "${tgt.list.basic}," not "full".
So after everything resolved, the target was now populated by the basic list.
I moved the full list out of the cfg file to be populated by the basic list later (instead of immediately)

VonC
Your first answer moved me forward enough to get it working. This: "^tgt.list.full=([^,]+),?.*" plus re-arranging the tgt.list.full was enough to fix the problem.
Adam
Great. Glad it worked out for you.
VonC
To clarify: The "target" prop was actually being populated by "${tgt.list.basic}," not "full" so after everything resolved, the target was now populated by the basic list. I moved the full list out of the cfg file to be populated by the basic list later (instead of immediately).
Adam