Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我可以发送Ant';更换';任务输出到新文件?_Ant_Replace - Fatal编程技术网

我可以发送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" /> 我希望那些替换了标记的文件以

Ant
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" />