I'm trying to change an xml element value from "true" to "false" using ANT replaceregexp task but am having difficulties matching across a new line. The relevant part of the XML node in question:
<validationRules>
<fullName>CAReversaApprovallLockdown</fullName>
<active>true</active>
In my text editor (sublime), I'm able to use the following regex to find/replace but I can't figure out how to replicate this in ANT replaceregexp:
/fullname>\n <active>true
I can't figure out the correct syntax to match the combination of the newline and the spacing afterwards. The spacing after the newline is always the same, if that makes things easier.
Looking at https://ant.apache.org/manual/Tasks/replaceregexp.html I've tried various combinations of ^ and $ with m flag, \s+ for spaces etc but just can't hit the right combo....any ideas?
My current progress is below but no luck unfortunately...
<target name="deactivate_val_rules">
<echo message="deactivating validation rules..." />
<replaceregexp match="/fullname>\r\n\s+<active>true" flags="gim" byline="false">
<substitution expression="/fullname>\r\n <active>false"/>
<fileset dir="src\objects" includes="Claim_Approvals__c.object"/>
</replaceregexp>
</target>
Got it - the following gave the correct result:
<target name="deactivate_val_rules">
<echo message="deactivating workflows..." />
<replaceregexp match="/fullname>\r\n\s+<active>true" flags="gis" byline="false">
<substitution expression="/fullname>${line.separator} <active>false"/>
<fileset dir="src\objects" includes="Claim_Approvals__c.object"/>
</replaceregexp>
</target>
The output viewed via diff is:
- <fullName>the_name</fullName>
- <active>true</active>
+ <fullName>the_name</fullname>
+ <active>false</active>
To Use replaceregexp you need to define the value to be changed as reference.
For Example:
<validationRules>
<fullName>CAReversaApprovallLockdown</fullName>
<active>true</active>
Ant:
<target name = "deactivate_val_rules">
<echo message="deactivating validation rules..." />
<replaceregexp file="${FILE_LOACTION}/FILE_NAME.FILE_EXT" match="true" replace="false" />
</target>
I have a requirement using ant, that the target should extract the two parameters passed as comma separated in a long list of similar pair of parameters passed which are semicolon separated. Currently I am doing something like this:
<?xml version="1.0"?>
<project name="" basedir="." default="test" xmlns:ac="antlib:net.sf.antcontrib">
<target name="test" >
<echo message="Hey There I am using What's App" />
<ac:for list="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu" delimiter=";" param="val">
<ac:sequential>
<ac:propertyregex property="param1"
input="#{val}"
regexp="([^\.]*)\,.*"
select="\1"
casesensitive="true" />
<ac:propertyregex property="param2"
input="#{val}"
regexp=".*,([^\.]*)"
select="\1"
casesensitive="true" />
<echo message = "val = ${param1}"/>
<echo message = "value = ${param2}"/>
</ac:sequential>
</ac:for>
</target>
</project>
But I am getting the output as:
Buildfile: /tmp/Manish/build.xml
test:
[echo] Hey There I am using What's App
[echo] val = asdfg
[echo] value = dasfdf
[echo] val = asdfg
[echo] value = dasfdf
[echo] val = asdfg
[echo] value = dasfdf
So this is getting looped 3 times(correct) but by only the first value passed in the for loop parameter. Is there some obvious mistake I am making?
Thanks,
Manish Joshi
Try using foreach instead of for and put the propertyregex into a separate target. Here is an example from my ant script, it basically does the same thing.
<target name="loadTestStatic" depends="setTargetEnv,setPassword">
<loadfile property="controlFile" srcFile="${projectDir}/test/config/static/controlFile.txt"/>
<foreach list="${controlFile}" delimiter="${line.separator}" param="descriptor" target="loadConfig"/>
</target>
<target name="loadConfig">
<if>
<matches string="${descriptor}" pattern="^camTool:"/>
<then>
<propertyregex property="camToolFile"
input="${descriptor}"
regexp="camTool:(.*)"
select="\1"
casesensitive="false" />
<echo message="Got cam tool file ${camToolFile}"/>
<camTool file="${camToolFile}"/>
</then>
<else>
<!-- todo: add CM Tool, SQL as required -->
<echo message="Unexpected config ${descriptor} ignored"/>
</else>
</if>
</target>
An alternative approach is to use a scripting language like groovy.
<groovy>
<arg value="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu"/>
args[0].tokenize(";").each {
def m = it.tokenize(",")
println "val = ${m[0]}"
println "value = ${m[1]}"
}
</groovy>
Alternatively use Ant addon Flaka, f.e. :
<project xmlns:fl="antlib:it.haefelinger.flaka">
<!-- with cvs property -->
<property name="foobar" value="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu"/>
<fl:for var="item" in="split('${foobar}', ';')">
<fl:let>
param1 ::= split(item, ',')[0]
param2 ::= split(item, ',')[1]
</fl:let>
<echo>
$${param1} => ${param1}
$${param2} => ${param2}
</echo>
</fl:for>
<!-- with list inline -->
<fl:for var="item" in="split('asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu', ';')">
<fl:let>
param1 ::= split(item, ',')[0]
param2 ::= split(item, ',')[1]
</fl:let>
<echo>
$${param1} => ${param1}
$${param2} => ${param2}
</echo>
</fl:for>
</project>
Notice the double '::' in param1 ::= split(item, ',')[0]
means overriding any (also userproperties, defined via -Dkey=value as commandline arguments) existing property
whereas ':=' creates a property but won't overwrite if property already exists.
<target name="myTarget">
<ac:propertyregex property="param1"
input="${myValue}"
regexp="([^\.]*)\,.*"
select="\1"
casesensitive="true" />
<ac:propertyregex property="param2"
input="${myValue}"
regexp=".*,([^\.]*)"
select="\1"
casesensitive="true" />
<echo message = "val = ${param1}"/>
<echo message = "value = ${param2}"/>
</target>
<ac:for list="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu" delimiter=";" param="val">
<ac:sequential>
<antcall target="myTarget">
<param name="myValue" value="#{val}" />
</antcall>
</ac:sequential>
</ac:for>
Properties in Ant are immutable. You will need to use the variable task from ant-contrib (although it is discouraged) to unset the properties:
<ac:for list="asdfg,dasfdf;vxxexqxx,hyyypyly;dksfgsgdgf,abaifuacu" delimiter=";" param="val">
<ac:sequential>
<ac:propertyregex property="param1"
input="#{val}"
regexp="([^\.]*)\,.*"
select="\1"
casesensitive="true" />
<ac:propertyregex property="param2"
input="#{val}"
regexp=".*,([^\.]*)"
select="\1"
casesensitive="true" />
<echo message = "val = ${param1}"/>
<echo message = "value = ${param2}"/>
<ac:var name="param1" unset="true"/>
<ac:var name="param2" unset="true"/>
</ac:sequential>
</ac:for>
I'm trying to create an ant build target that supports var substitution dynamically.
<target name="replace_property" depends="init_ant_contrib">
<propertyregex input="${replace_inboundproperty"
property="${replace_outboundproperty}"
regex="${replace_match}"
replace="${replace_target}"
global="true"
override="true" />
</target>
so I load the properties file and i'm basically setting the vars as such:
replace_inboundproperty="/target/path/targetfile"
replace_outboundproperty=blah
replace_match="/target/(.*)/targetfile"
replace_target="\1"
so when I echo blah, I'm getting "1". Now if I actually do this:
<target name="replace_property" depends="init_ant_contrib">
<propertyregex input="${replace_inboundproperty"
property="${replace_outboundproperty}"
regex="${replace_match}"
replace="\1"
global="true"
override="true" />
</target>
and echo blah, I'll get "path".
Can anyone tell me what I'm missing to allow the replace to use capture groups from a properties file / ant -D? Using ant-contrib 1.0b3.
Thanks!
Found out that in the properties file, if you double escape it, it'll function correctly:
replace_target=\\1
I have the following
<RegexMatch Input="$(Configuration)" Expression="^.*?(?=\.)">
<Output ItemName="Theme" TaskParameter="Output" />
</RegexMatch>
My configuration variable is as follows Theme.Environment
So "Default.Debug"
or "Yellow.Release"
I would like to get the first portion in to a varaible called theme.
I have tested this regex and it works in stand alone regex testers
^.*?(?=\.)
but not when used in my build file.
I am echoing the variable out so that i can see the output
<Exec Command="echo $(Theme)"/>
<Exec Command="echo $(Configuration)"/>
Ideas?
If you should use MSBuild Community tasks for that - check this line: <Output PropertyName="Theme" TaskParameter="Output" />
you should use PropertyName="Theme" if you want to refer it like $(Theme) later.
ItemName will create items set, not property.
But it's much simplier to use MSBuild 4.0 inline functions than Msbuild community tasks for that concrete task. Your code will looks like this (adopt for your script):
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTarget="Play">
<PropertyGroup>
<Configuration>Yellow.Release</Configuration>
</PropertyGroup>
<Target Name="Play">
<PropertyGroup>
<Theme>$([System.Text.RegularExpressions.Regex]::Match($(Configuration), `^.*?(?=\.)`))</Theme>
</PropertyGroup>
<Message Text="$(Theme)" />
<Message Text="$(Configuration)" />
</Target>
</Project>
Just realised that RegexMatch doenst return the matched string but rather returns the entire string if matched.
basically it called IsMatch method not Match method
Have re written as a RegexReplace
<RegexReplace Input="$(Configuration)" Expression="\..*" Replacement="" Count="1">
<Output ItemName="Theme" TaskParameter="Output" />
</RegexReplace>
After that it still wasnt working and then i realised i was doing
$(Theme)
Should have been
#(Theme)
Im trying to count the number of occurences of the line "Does this buildlist need compile: true" in a file. I tried the following code, but it does not pick up the count
<concat>
<fileset file="#{logPathInTestSetup}" />
<filterchain>
<tokenfilter>
<ct:countfilter property="noOfCompiledBuildlists" contains="Does this buildlist need compile:\s*(true)" override="true">
<ct:counteach propertyprefix="count." select="\1" />
</ct:countfilter>
</tokenfilter>
<ct:stopfilter />
</filterchain>
</concat>
When I try counting "Does this buildlist need compile:", the counter works and I get the correct value. So there is definitely a problem with the regex. Can someone please help?
Thanks,
Aarthi
You don't need some extra task, but Ant 1.7.1+ as <concat> has to be resource.
Here's a slightly adapted example from ant manual resourcecount
given input, foobar.txt :
Does this buildlist need compile: true
whatever
Does this buildlist need compile: false
The quick brown fox
jumps over the lazy dog
Does this buildlist need compile: true
Does this buildlist need compile: false
Does this buildlist need compile: true
foo
blablabla
Does this buildlist need compile: true
example ant script :
<project>
<property name="file" value="foobar.txt"/>
<resourcecount property="file.lines">
<tokens>
<concat>
<filterchain>
<linecontainsregexp>
<regexp pattern="Does this buildlist need compile:\s*(true)"/>
</linecontainsregexp>
</filterchain>
<fileset file="${file}"/>
</concat>
</tokens>
</resourcecount>
<echo>The file '${file}' has ${file.lines} lines.</echo>
</project>
output :
[echo] The file 'foobar.txt' has 4 lines.
EDIT
To get the lines that do not match, means negate your regex, simply use :
</linecontainsregexp negate="true">