我正在编写一个Ant脚本,用于从属性文件中删除内容。
假设属性文件名为abc.properties,其中一个属性是这样的:
this.property=monkey,banana,peanuts,ate,tiger,what,the,heck
我的脚本必须能够在不影响订单的情况下删除其中一个项目。现在,我有这个:
<replaceregexp file="@{targetDir}/setup/properties/abc.properties"
match="this.property(.*),tiger(.*)"
replace="this.property\1\2"/>
目前,正则表达式适用于除猴子之外的任何事情。我可以用什么,花生或除猴子以外的任何东西取代老虎,因为它们都在他们面前有逗号。如果我从匹配表达式中删除了逗号,则会有一个额外的逗号。问题是,我将如何编写将替换任何项目的正则表达式,包括猴子?
由于
答案 0 :(得分:2)
2011年7月10日编辑,纳入了有关inTide的优秀建议:
怎么样
match="this.property(.*[=,])tiger(?:,|$)(.*)"
replace="\1\2"
这将留下一个伪造的“逗”的逗号 - 最后的选择。删除这是第二遍:
match="(this.property.*?)(?:,$|$)"
replace="\1"
答案 1 :(得分:1)
这会有用吗?
<!-- Handle the case when tiger is first -->
<replaceregexp file="@{targetDir}/setup/properties/abc.properties"
match="this.property=tiger,(.*)"
replace="this.property=\1"/>
<!-- Handle all other cases -->
<replaceregexp file="@{targetDir}/setup/properties/abc.properties"
match="this.property=(.*),tiger(.*)"
replace="this.property=\1\2"/>
这是一个kludge,我承认(并且你需要第三个案例来处理当Tiger是列表中唯一的项目时),但它可能会起作用。
答案 2 :(得分:1)
尝试使用:
match="(this.property=(?:.*,)?)tiger(?:,|$)" replace="\1"
更新:要删除一个可能的周围逗号,需要更多的工作。如果你在Ant支持的条件中使用正则表达式lib,你可以借助(?(2),)
之类的东西来解决它。但由于你可能正在使用Javas默认的Regex lib,你必须使用交替,例如:
match="(this.property=(?:[^,]*(?:,[^,]*)*)?)(?:,tiger(?=,|$)|(?<==)tiger(?:,|$))" replace="\1"
Perl测试:
my @strings = (
'this.property=monkey,banana,peanuts,ate,tiger,what,the,heck',
'this.property=monkey,banana,peanuts,ate,tiger',
'this.property=tiger,what,the,heck',
'this.property=tiger',
);
my $re = qr/(this.property=(?:[^,]*(?:,[^,]*)*)?)(?:,tiger(?=,|$)|(?<==)tiger(?:,|$))/;
for(@strings){
print ">> \"$_\"\n";
s/$re/$1/g;
print " \"$_\"\n";
}
输出:
>> "this.property=monkey,banana,peanuts,ate,tiger,what,the,heck"
"this.property=monkey,banana,peanuts,ate,what,the,heck"
>> "this.property=monkey,banana,peanuts,ate,tiger"
"this.property=monkey,banana,peanuts,ate"
>> "this.property=tiger,what,the,heck"
"this.property=what,the,heck"
>> "this.property=tiger"
"this.property="
答案 3 :(得分:1)
我尝试了几个正则表达式,但没有得到一个,最接近的是:
<replaceregexp file="props.txt"
match="(this.property=[,?\w+,?]*)monkey,(.*)"
replace="\1\2"
/>
注意猴子后面的',',
案例第一项=猴子,你必须使用:
match="(this.property=[,?\w+,?]*)monkey,(.*)"<br>
摆脱','否则:
match="(this.property=[,?\w+,?]*)monkey(.*)"
你会得到
this.property=,banana,peanuts,ape,tiger,what,the,heck
在shold被删除的项目之后使用尾随','将适用于所有其他项目,例如:香蕉也是,但不是
最后一项。
case last item = heck:
match="(this.property=[,?\w+,?]*)heck,(.*)"
不会做任何事情
match="(this.property=[,?\w+,?]*)heck(.*)"
会得到:
this.property=monkey,banana,peanuts,ape,tiger,what,the,
仅限:
match="(this.property=[,?\w+,?]*),heck"
会起作用。
所以,没有通用的解决方案,因为','
的问题因为必须使用多个步骤,才能使其适用于所有情况
因此,要么使用多个replaceregexp部件,要么反过来使用,意味着加载属性文件,然后直接编辑属性 - propertyfile保持不变。
由于ant中的属性在设计上是不可变的,因此您必须使用一些Ant Addon或一种可以访问ant api的脚本语言来实现此目的。
使用macrodef处理所有案例,使用Flaka:
<project xmlns:fl="antlib:it.haefelinger.flaka">
<property name="this.property" value="monkey,banana,peanuts,ape,tiger,what,the,heck"/>
<macrodef name="editcsvproperty">
<attribute name="csvproperty"/>
<attribute name="newproperty"/>
<attribute name="delete"/>
<sequential>
<fl:when test="'@{csvproperty}' eq '@{newproperty}'">
<echo>Overriding existing property => '@{csvproperty}' !!</echo>
</fl:when>
<fl:let>
; first delete item itself
@{newproperty} ::= replace(property['@{csvproperty}'], '', '@{delete}')
; take care of doubled ,,
@{newproperty} ::= replace(property['@{csvproperty}'], ',', ',,')
; take care of a leading ,
@{newproperty} ::= replace(property['@{csvproperty}'], '$1', '^,(.+)')
; take care of a trailing ,
@{newproperty} ::= replace(property['@{csvproperty}'], '$1', '(.+),$')
</fl:let>
</sequential>
</macrodef>
<editcsvproperty
csvproperty="this.property"
newproperty="this.property"
delete="heck"
/>
<echo>$${this.property} => ${this.property}</echo>
</project>
答案 4 :(得分:1)
像
这样的东西<replaceregexp
file="@{targetDir}/setup/properties/abc.properties"
match="(this.property.*)(?:@{toRemove},|,@{toRemove})"
replace="\1"
/>
答案 5 :(得分:1)
这并不像看起来那么难。以下适用于所有情况,除非关键字是唯一的情况。 (对于这种情况,只需添加另一条规则。)
<replaceregexp file="@{targetDir}/setup/properties/abc.properties"
match="this\.property=(.*)(?:,tiger\b|\btiger,)(.*)"
replace="this.property\1\2"/>
答案 6 :(得分:0)
在Python中,我会这样做:
import re
ch = 'this.property=monkey,banana,tigerfish,peanuts,ate,tiger,what,the,heck'
print ch
print '-----------------------------------------------------------'
for word in ('tiger','heck','monkey'):
regx = re.compile('(?<=this\.property=)(.*?)(,)?%s(?(2)(?=(?:,|$))|,)(.*)' % word, re.M)
print 'word=='+word
print regx.sub('\\1\\3',ch)
print
print
ch = 'this.property=monkey'
print ch
print '-----------------------------------------------------------'
regx = re.compile('(?<=this\.property=)(.*?)(,)?%s(?(2)(?=(?:,|$))|(?:,|$))(.*)' % 'monkey', re.M)
print 'monkey'
print regx.sub('\\1\\3',ch)
结果
this.property=monkey,banana,tigerfish,peanuts,ate,tiger,what,the,heck
-----------------------------------------------------------
word==tiger
this.property=monkey,banana,tigerfish,peanuts,ate,what,the,heck
word==heck
this.property=monkey,banana,tigerfish,peanuts,ate,tiger,what,the
word==monkey
this.property=banana,tigerfish,peanuts,ate,tiger,what,the,heck
this.property=monkey
-----------------------------------------------------------
monkey
this.property=
答案 7 :(得分:0)
添加直接与属性文件一起使用的自定义ant任务将更加坚固。 (ant可以调用java程序,因此可能是另一种选择)。由于ant允许在javascript(rhino)中使用java程序,我试过下面的代码..你可以根据需要进行调整..
<project name="blah" default="editprops" basedir=".">
<target name="editprops" >
<property file="try.props"/>
<script language="javascript"> <![CDATA[
importClass(java.util.Properties);
importClass(java.io.FileReader);
importClass(java.io.FileWriter);
importClass(java.io.IOException);
var properties = new Properties();
var reader = new FileReader("try.prop");
properties.load(reader);
var tt = properties.getProperty("this.property");
var ll= tt.split ( ",");
var newval="";
var i=0;
for ( i =0; i< ll.length ; i++ ) {
if ( ll[i] == "monkey" ) {
continue;
}
if ( newval=="" ) {
newval = ll[i];
}
else {
newval = newval + "," + ll[i];
}
}
print ( newval);
properties.setProperty("this.property", newval);
var writer = new FileWriter ( "try.new");
properties.store( writer, "today" );
]]></script>
</target>
</project>