我可以发送Ant';更换';任务输出到新文件?
Ant我可以发送Ant';更换';任务输出到新文件?,ant,replace,Ant,Replace,Antreplace任务在不创建新文件的情况下执行就地替换 下面的代码段使用“my.properties”文件中的相应值替换任意“*.xml”文件中的标记 <replace dir="${projects.prj.dir}/config" replacefilterfile="${projects.prj.dir}/my.properties" includes="*.xml" summary="true" /> 我希望那些替换了标记的文件以
replace
任务在不创建新文件的情况下执行就地替换
下面的代码段使用“my.properties”文件中的相应值替换任意“*.xml”文件中的标记
<replace dir="${projects.prj.dir}/config"
replacefilterfile="${projects.prj.dir}/my.properties"
includes="*.xml" summary="true" />
我希望那些替换了标记的文件以模式命名(例如“*.xml.filtered”),并保留原始文件
这在Ant中是否可能与一些智能任务组合在一起?替换任务不观察依赖关系,而是通过为每个输入文件编写一个临时文件来执行替换。如果临时文件与输入文件相同,则该文件将被丢弃。重命名与输入文件不同的临时文件以替换该输入。这意味着所有的文件都会被处理,即使它们都不需要被处理——因此效率很低 这个问题最初的解决办法是进行复制-替换复制。但是不需要第二个副本,因为可以在第一个副本中使用映射器。在副本中,依赖项可用于将处理仅限于已更改的文件-通过显式文件集中的:
<copy todir="${projects.prj.dir}">
<fileset dir="${projects.prj.dir}">
<include name="*.xml" />
<depend targetdir="${projects.prj.dir}">
<mapper type="glob" from="*.xml" to="*.xml.filtered" />
</depend>
</fileset>
<mapper type="glob" from="*.xml" to="*.xml.filtered" />
</copy>
这将防止replace
任务不必要地处理以前进行过替换的文件。但是,它不会阻止处理未更改且不需要替换的文件
除此之外,我不确定是否有办法对这个问题进行“编码”,将步骤数减少到一个。
在copy
任务中没有多字符串替换筛选器可以实现与replace
相同的效果,这是一个遗憾,因为感觉它是正确的解决方案
另一种方法是为一系列replace string
过滤器生成xml,然后让Ant执行。但这将比现有的解决方案更复杂,并且容易出现替换字符串的问题,如果粘贴到xml片段中,将导致无法解析的内容
另一种方法是编写一个自定义任务或脚本
任务来完成这项工作。如果存在多个文件,并且“复制-替换”解决方案被认为太慢,那么这可能就是解决方法。但同样,这种方法不如现有的解决方案简单
如果需求是最小化处理过程中所做的工作,而不是提出最短的Ant解决方案,那么这种方法就可以了
- 创建一个包含已更改输入列表的文件集
- 从该文件集创建一个以逗号分隔的相应过滤文件列表
- 在文件集上执行复制
- 在逗号分隔的列表上执行替换
<fileset id="changed" dir="${projects.prj.dir}" includes="*.xml">
<depend targetdir="${projects.prj.dir}">
<globmapper from="*.xml" to="*.xml.filtered" />
</depend>
</fileset>
<pathconvert property="replace.includes" refid="changed">
<map from=".xml" to=".xml.filtered" />
</pathconvert>
<copy todir="${projects.prj.dir}" preservelastmodified="true">
<fileset refid="changed" />
<globmapper from="*.xml" to="*.xml.filtered" />
</copy>
<replace dir="${projects.prj.dir}"
replacefilterfile="my.properties"
includes=".dummy,${replace.includes}" summary="true" />
有几种方法可以接近您想要的内容,而无需复制到临时目录并复制回来 过滤器组 如果可以更改源文件,以便使用开始和结束标记来分隔要替换的部件,如
@date@
(@
是默认标记,但可以更改),则可以使用a和a:
这将在文件中的任何位置将出现的foo
替换为bar
,这更像是replace
任务的行为。不幸的是,这种方式意味着您需要在构建文件本身中包含所有替换项,而不能将它们放在单独的属性文件中
在这两种情况下,copy
任务将只复制比目标文件更新的源文件,因此不会执行不必要的工作
复制然后替换
第三种可能性(我在写其他两种文件时刚刚想到)是首先对重命名的文件执行复制,然后运行replace
任务,指定重命名的文件:
<copy todir="config">
<fileset dir="config" includes="*.xml" />
<globmapper from="*.xml" to="*.xml.filtered" />
</copy>
<replace dir="config" replacefilterfile="replace.properties" summary="true"
includes="*.xml.filtered" />
这可能是最接近原始需求的解决方案。缺点是每次对重命名的文件运行replace
任务。对于某些替换模式来说,这可能是一个问题(诚然,它们可能是像foo=foofoo
这样的奇怪模式,但对于前两种方法,它们是可以接受的),并且当依赖项没有改变时,您将做不必要的工作
<replace dir="${projects.prj.dir}"
replacefilterfile="my.properties">
includes=".dummy" />
<fileset dir="${projects.prj.dir}" includes="*.xml.filtered">
<not>
<different targetdir="${projects.prj.dir}">
<globmapper from="*.xml.filtered" to="*.xml" />
</different>
</not>
</fileset>
</replace>
<fileset id="changed" dir="${projects.prj.dir}" includes="*.xml">
<depend targetdir="${projects.prj.dir}">
<globmapper from="*.xml" to="*.xml.filtered" />
</depend>
</fileset>
<pathconvert property="replace.includes" refid="changed">
<map from=".xml" to=".xml.filtered" />
</pathconvert>
<copy todir="${projects.prj.dir}" preservelastmodified="true">
<fileset refid="changed" />
<globmapper from="*.xml" to="*.xml.filtered" />
</copy>
<replace dir="${projects.prj.dir}"
replacefilterfile="my.properties"
includes=".dummy,${replace.includes}" summary="true" />
<copy todir="config">
<fileset dir="config" includes="*.xml" />
<globmapper from="*.xml" to="*.xml.filtered" />
<filterset filtersfile="replace.properties" />
</copy>
<copy todir="config">
<fileset dir="config" includes="*.xml" />
<globmapper from="*.xml" to="*.xml.filtered" />
<filterchain>
<tokenfilter>
<replacestring from="foo" to="bar" />
<!-- extra replacestring elements here as required -->
</tokenfilter>
</filterchain>
</copy>
<copy todir="config">
<fileset dir="config" includes="*.xml" />
<globmapper from="*.xml" to="*.xml.filtered" />
</copy>
<replace dir="config" replacefilterfile="replace.properties" summary="true"
includes="*.xml.filtered" />