替换Ant属性中的字符


90

是否有一种简单的方法来获取属性的值,然后将其复制到替换了某些字符的另一个属性中?

propA=This is a value。我想将其中的所有空格替换为下划线,结果为propB=This_is_a_value

Answers:


89

使用Ant Contribpropertyregex任务。

我想你要:

<propertyregex property="propB"
               input="${propA}"
               regexp=" "
               replace="_"
               global="true" />

不幸的是,给出的例子还不是很清楚,但是值得尝试。您还应该检查如果没有任何下划线,会发生什么情况-您可能还需要使用该defaultValue选项。


3
defaultValue="${propA}"作为一般的搜索/替换单行代码,添加是完美的:否则,如果没有匹配项,则propB中什么都不会放入!谢谢!
David Robson

107

这是没有脚本并且没有像ant-conrib这样的外部jar的解决方案:

诀窍是使用ANT的资源:

  • 有一种称为“ propertyresource”的资源类型,它类似于源文件,但是从该资源的字符串值提供流。因此,您可以加载它并在接受文件的“复制”之类的任何任务中使用它
  • 还有一个任务“ loadresource”可以将任何资源加载到属性(例如文件),但是此任务也可以加载我们的propertyresource。此任务允许通过应用一些令牌转换来过滤输入。最后,以下将满足您的要求:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

这将用“ _”替换propA中的所有“”并将结果放入propB中。“ filetokenizer”将整个输入流(我们的属性)视为一个令牌,并在其上加上字符串替换。

您可以使用其他令牌过滤器进行其他精美的转换:http ://ant.apache.org/manual/Types/filterchain.html


7
谢谢!事实证明,您甚至可以删除该<filetokenizer/>位。没有它,您的代码就可以正常工作(至少在Ant v1.8.3上)。
Matthias

如果您尝试从Maven内部执行此操作,请参阅stackoverflow.com/a/22969187/2163960
user2163960 2014年

3
支持一种适用于香草ant且不需要其他库的技术。
Christopher Schultz

57

如果不能选择ant-contrib,那么这是Java 1.6及更高版本的可移植解决方案:

<property name="before" value="This is a value"/>
<script language="javascript">
    var before = project.getProperty("before");
    project.setProperty("after", before.replaceAll(" ", "_"));
</script>
<echo>after=${after}</echo>

6
如果使用此方法,最好将脚本包含在CDATA中,以避免xml解析出现问题。<script language =“ javascript”> <![CDATA [// Java脚本代码可以安全地使用'<'字符。]]> </ script>
Jan Arciuchiewicz 2012年

3
@dnault Javascript没有replaceAll字符串功能。使用before.replace( /\s/g, "_" )代替。
拉里·

3
@LarryBattle project.getProperty()返回a java.lang.String,因此replaceAll()在这种情况下是合适的。如果要使用replace(),则可以使用以下命令将“之前”转换为本地JavaScript字符串:before = new String(before);
dnault,2012年

1
project.setNewProperty会更容易移植,因为setProperty可能会覆盖旧的属性值。它甚至可以写入before属性。
Jarekczek 2012年

它需要Rhino
vintproykt

26

如果您想要一个使用Ant内置组件的解决方案,请考虑以下事项:

<target name="replace-spaces">
    <property name="propA" value="This is a value" />
    <echo message="${propA}" file="some.tmp.file" />
    <loadfile property="propB" srcFile="some.tmp.file">
        <filterchain>
            <tokenfilter>
                <replaceregex pattern=" " replace="_" flags="g"/>
            </tokenfilter>
        </filterchain>
    </loadfile>
    <echo message="$${propB} = &quot;${propB}&quot;" />
</target>

输出是 ${propB} = "This_is_a_value"


2
谁清理some.tmp.file?
ceving 2014年

由于其他人可能想使用它;在</ loadfile>之后添加<delete file =“ some.tmp.file” />。答案@ceving问题:)
terix2k11

8

使用某些外部应用程序,例如sed:

<exec executable="sed" inputstring="${wersja}" outputproperty="wersjaDot">
  <arg value="s/_/./g"/>
</exec>
<echo>${wersjaDot}</echo>

如果您运行Windows,请使用Google搜索“ gnuwin32 sed”。

该命令s/_/./g用替换所有命令_. 此脚本在Windows下运行良好。在linux下arg可能需要引用。


8

两种可能性:

通过脚本任务和内置的javascript引擎(如果使用jdk> = 1.6)

<project>

 <property name="propA" value="This is a value"/>

 <script language="javascript">
  project.setProperty('propB', project.getProperty('propA').
   replace(" ", "_"));
 </script>
 <echo>$${propB} => ${propB}</echo>

</project>

或使用Ant插件Flaka

<project xmlns:fl="antlib:it.haefelinger.flaka">

 <property name="propA" value="This is a value"/>

 <fl:let> propB := replace('${propA}', '_', ' ')</fl:let>

 <echo>$${propB} => ${propB}</echo>

</project>

覆盖现有属性propA只需将propB替换为propA


7

这是Uwe Schindler的答案的更一般化的版本:

您可以使用macrodef来创建自定义任务。

<macrodef name="replaceproperty" taskname="@{taskname}">
    <attribute name="src" />
    <attribute name="dest" default="" />
    <attribute name="replace" default="" />
    <attribute name="with" default="" />
    <sequential>
        <loadresource property="@{dest}">
            <propertyresource name="@{src}" />
            <filterchain>
                <tokenfilter>
                    <filetokenizer/>
                    <replacestring from="@{replace}" to="@{with}"/>
                </tokenfilter>
            </filterchain>
        </loadresource>
    </sequential>
</macrodef>

您可以按以下方式使用它:

<replaceproperty src="property1" dest="property2" replace=" " with="_"/>

如果您多次这样做,这将非常有用


3

以前的答案上添加答案更完整的示例

<property name="propB_" value="${propA}"/>
<loadresource property="propB">
  <propertyresource name="propB_" />
  <filterchain>
    <tokenfilter>
      <replaceregex pattern="\." replace="/" flags="g"/>
    </tokenfilter>
  </filterchain>
</loadresource>

1

只是一个供您回答的FYI 替换Ant属性中的字符 -如果您试图在maven执行中使用它,则不能直接引用maven变量。您将需要以下内容:

...
<target>
<property name="propATemp" value="${propA}"/>
    <loadresource property="propB">
    <propertyresource name="propATemp" />
...

涉及到更换什么零件" ""_"
Jin Kwon

另外,在行家中,您可以propATemp 通过<propertyresource name="propATemp"/>使用<string value="${propA}"/>
Ed Randall

1

属性不能更改,但antContrib vars(http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html)可以更改。

这是在var上查找/替换的宏:

    <macrodef name="replaceVarText">
        <attribute name="varName" />
        <attribute name="from" />
        <attribute name="to" />
        <sequential>
            <local name="replacedText"/>
            <local name="textToReplace"/>
            <local name="fromProp"/>
            <local name="toProp"/>
            <property name="textToReplace" value = "${@{varName}}"/>
            <property name="fromProp" value = "@{from}"/>
            <property name="toProp" value = "@{to}"/>

            <script language="javascript">
                project.setProperty("replacedText",project.getProperty("textToReplace").split(project.getProperty("fromProp")).join(project.getProperty("toProp")));
            </script>
            <ac:var name="@{varName}" value = "${replacedText}"/>
        </sequential>
    </macrodef>

然后像这样调用宏:

<ac:var name="updatedText" value="${oldText}"/>
<current:replaceVarText varName="updatedText" from="." to="_" />
<echo message="Updated Text will be ${updatedText}"/>

上面的代码使用javascript split然后加入,比regex快。“本地”属性将传递给JavaScript,因此不会发生属性泄漏。


0

或者...您也可以尝试自己的任务

JAVA代码:

class CustomString extends Task{

private String type, string, before, after, returnValue;

public void execute() {
    if (getType().equals("replace")) {
        replace(getString(), getBefore(), getAfter());
    }
}

private void replace(String str, String a, String b){
    String results = str.replace(a, b);
    Project project = getProject();
    project.setProperty(getReturnValue(), results);
}

..all getter and setter..

蚂蚁脚本

...
<project name="ant-test" default="build">

<target name="build" depends="compile, run"/>

<target name="clean">
    <delete dir="build" />
</target>

<target name="compile" depends="clean">
    <mkdir dir="build/classes"/>
    <javac srcdir="src" destdir="build/classes" includeantruntime="true"/>
</target>

<target name="declare" depends="compile">
    <taskdef name="string" classname="CustomString" classpath="build/classes" />
</target>

<!-- Replacing characters in Ant property -->
<target name="run" depends="declare">
    <property name="propA" value="This is a value"/>
    <echo message="propA=${propA}" />
    <string type="replace" string="${propA}" before=" " after="_" returnvalue="propB"/>
    <echo message="propB=${propB}" />
</target>

安慰:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.