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 having trouble copying some files which match a pattern in my ant script.
I have the following:
<property name="IncludedLocales" value="de_DE|es_ES|fr_FR|it_IT|ja_JP" />
<copy todir="${dest}">
<fileset dir="${src}" includes="**/*.properties" />
<mapper type="regexp" from="(messages(_${IncludedLocales})?\.properties)" to="\1" />
</copy>
${src} contains the files messages.properties, as well as messages_de_DE.properties, messages_es_ES.properties, etc.
But for some reason, only messages.properties, and messages_de_DE.properties get copied (and if I changed IncludedLocales to 'es_ES|de_DE|fr_FR|it_IT|ja_JP', messages_es_ES.properties gets copied instead of messages_de_DE.properties).
Am I missing something really simple?
Yes, I did miss something really simple, (messages(_${IncludedLocales})?\.properties) should have been (messages(_(${IncludedLocales}))?\.properties)
Based on this thread. I've tried to replace the set the current version of my project in my NAnt script.
Here's my Replace snippet
<target name="Replace">
<loadfile file="${SetVersionCpp.File}" property="h.file.content" />
<regex
input="${h.file.content}"
pattern="(?'BEFORE'[.\s]*)${LineBegining}\s*[\s\d,]*\r\n(?'AFTER'[.\s]*)" />
<echo
file="${SetVersionCpp.File}"
message="${BEFORE}${LineBegining} ${ReplaceWith}
${AFTER}"
append="false"
verbose="true" />
</target>
Which I call on this file
#define FILEVER 0, 2, 0, 3
#define PRODUCTVER 0, 2, 0, 3
#define STRFILEVER "00.02.00.03\0"
#define STRPRODUCTVER "00.02.00.03\0"
with the following parameters
<property name="SetVersionCpp.File" value="${baseline.dir}\VersionNo.h" />
<property name="LineBegining" value="#define FILEVER" />
<property name="ReplaceWith" value="${FileVersion}" />
Based on the output, the AFTER variable is not capturing the rest of the file for some reason. This is what I get:
[#define FILEVER 0, 2, 0, 30
]
*I put it in brackets so that the whitespace got correctly formatted
Any ideas what I'm doing wrong?
I've fixed it by setting the options to Singleline so that . would match line breaks and by removing the classes from the groups:
<regex
input="${h.file.content}"
options="Singleline"
pattern="(?'BEFORE'.*)${LineBegining}\s*[\s\d,]*\r\n(?'AFTER'.*)" />
I need to replace all occurrence of some regular expression in xml file with proper values loaded from property file. As example
in xml file I have < port=${jnpPort}/>
in property file I have port=3333
I want to have xml file with entries like < port=3333/>
Now using
<replaceregexp match="\$\{(.*)\}" replace="${\1}" flags="g" byline="true">
<fileset dir="." includes="file.xml"/>
</replaceregexp>
I get pretty much the same <port=${jnpPort} />. I would like value of ${jnpPort} were read from property file.
Try:
<replaceregexp match="#< port=\${jnpPort}/>#" replace="#< port=$(port)/>#" flags="g" byline="true">
<fileset dir="." includes="file.xml"/>
</replaceregexp>
You just use copy with a filterset
<filterset id="version.properties.filterset" begintoken="$" endtoken="$">
<filter token="jnpPort" value="${port}" />
</filterset>
<copy file="file.xml.template" tofile="file.xml" overwrite="true" >
<filterset refid="version.properties.filterset" />
</copy>
Okay, not quite copy in place, but pretty good.