Ersetzen von Zeichen in der Ant-Eigenschaft

90

Gibt es eine einfache Möglichkeit, den Wert einer Eigenschaft zu übernehmen und dann in eine andere Eigenschaft zu kopieren, wobei bestimmte Zeichen ersetzt werden?

Sagen Sie propA=This is a value. Ich möchte alle darin enthaltenen Leerzeichen durch Unterstriche ersetzen, was zu propB=This_is_a_value.

aberrant80
quelle

Antworten:

89

Verwenden Sie die Eigenschaft propertyregex von Ant Contrib .

Ich denke du willst:

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

Leider sind die Beispiele nicht besonders klar, aber es lohnt sich, das zu versuchen. Sie sollten auch überprüfen, was passiert, wenn keine Unterstriche vorhanden sind. Möglicherweise müssen Sie die defaultValueOption auch verwenden.

Jon Skeet
quelle
3
Das Hinzufügen defaultValue="${propA}"ist perfekt als allgemeine Suche / Ersetzung eines Einzeilers: Andernfalls wird nichts in propB eingefügt, wenn keine Übereinstimmung vorliegt !! Vielen Dank!
David Robson
105

Hier ist die Lösung ohne Scripting und ohne externe Gläser wie Ant-Conrib:

Der Trick besteht darin, die Ressourcen von ANT zu nutzen:

  • Es gibt einen Ressourcentyp namens "propertyresource", der einer Quelldatei ähnelt, jedoch einen Stream aus dem Zeichenfolgenwert dieser Ressource bereitstellt. Sie können es also laden und in jeder Aufgabe wie "Kopieren" verwenden, die Dateien akzeptiert
  • Es gibt auch die Aufgabe "loadresource", die jede Ressource in eine Eigenschaft (z. B. eine Datei) laden kann, aber diese könnte auch unsere propertyresource laden. Diese Aufgabe ermöglicht das Filtern der Eingabe durch Anwenden einiger Token-Transformationen. Schließlich wird das Folgende tun, was Sie wollen:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Dieser ersetzt alle "" in propA durch "_" und platziert das Ergebnis in propB. "filetokenizer" behandelt den gesamten Eingabestream (unser Eigentum) als ein Token und wendet den String-Ersatz darauf an.

Sie können andere ausgefallene Transformationen mit anderen Tokenfiltern durchführen: http://ant.apache.org/manual/Types/filterchain.html

Uwe Schindler
quelle
7
Vielen Dank! Es stellt sich heraus, dass Sie das <filetokenizer/>Bit sogar fallen lassen können . Ihr Code funktioniert ohne ihn einwandfrei (zumindest unter Ant v1.8.3).
Matthias
Wenn Sie versuchen, dies von Maven aus zu tun, lesen
user2163960
3
Upvote für eine Technik, die in Vanille antfunktioniert und keine zusätzlichen Bibliotheken erfordert.
Christopher Schultz
57

Wenn Ant-Contrib keine Option ist, finden Sie hier eine tragbare Lösung für Java 1.6 und höher:

<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>
dnault
quelle
6
Wenn diese Methode verwendet wird, ist es gut, ein Skript in CDATA einzuschließen, um Probleme mit der XML-Analyse zu vermeiden. <script language = "javascript"> <! [CDATA [// Java-Skriptcode kann sicher das Zeichen '<' verwenden. ]]> </ script>
Jan Arciuchiewicz
3
@dnault Javascript hat keine replaceAllFunktion für Zeichenfolgen. Verwenden Sie before.replace( /\s/g, "_" )stattdessen.
Larry Battle
3
@LarryBattle project.getProperty()gibt a zurück java.lang.String, replaceAll()ist also in diesem Fall angemessen. Wenn Sie verwenden replace()before = new String(before);
möchten
1
project.setNewPropertywäre portabler, da setPropertyalter Immobilienwert überschrieben werden könnte. Es könnte sogar auf das beforeGrundstück schreiben .
Jarekczek
Es erfordert Rhino
vintproykt
26

Falls Sie eine Lösung , die Verwendung Ant Einbauten funktioniert nur , bedenken Sie:

<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>

Ausgabe ist ${propB} = "This_is_a_value"

mgaert
quelle
2
Wer bereinigt some.tmp.file?
Ceving
Da andere dies vielleicht nutzen möchten; Fügen Sie nach </ loadfile> <delete file = "some.tmp.file" /> hinzu. Antworten @ceving Frage :)
terix2k11
8

Verwenden Sie eine externe App wie sed:

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

Wenn Sie Windows ausführen, googeln Sie nach "gnuwin32 sed".

Der Befehl s/_/./gersetzt alle _durch . Dieses Skript funktioniert gut unter Windows. Unter Linux muss arg möglicherweise zitiert werden.

Jarekczek
quelle
8

Zwei Möglichkeiten:

über Skriptaufgabe und eingebaute Javascript-Engine (bei Verwendung von 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>

oder mit Ant Addon 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>

Um vorhandene Eigenschaften propA zu überschreiben, ersetzen Sie einfach propB durch propA

Rebse
quelle
7

Hier ist eine allgemeinere Version von Uwe Schindlers Antwort :

Mit a können Sie macrodefeine benutzerdefinierte Aufgabe erstellen.

<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>

Sie können dies wie folgt verwenden:

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

Dies ist sehr nützlich, wenn Sie dies mehrmals tun

Avinash R.
quelle
3

Hinzufügen einer Antwort vollständigeres Beispiel gegenüber einer vorherigen Antwort

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

Nur ein FYI für die Antwort Ersetzen von Zeichen in der Ant-Eigenschaft - Wenn Sie versuchen, dies innerhalb einer Maven-Ausführung zu verwenden, können Sie nicht direkt auf Maven-Variablen verweisen. Sie benötigen so etwas:

...
<target>
<property name="propATemp" value="${propA}"/>
    <loadresource property="propB">
    <propertyresource name="propATemp" />
...
user2163960
quelle
Welche Teile bezogen auf den Ersatz " "zu "_"?
Jin Kwon
Alternativ in Maven, können Sie die Notwendigkeit, den Einsatz Eigentum vermeiden propATemp durch Ersetzen <propertyresource name="propATemp"/>mit<string value="${propA}"/>
Ed Randall
1

Eigenschaften können nicht geändert werden, aber antContrib-Variablen ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html) ) jedoch.

Hier ist ein Makro zum Suchen / Ersetzen einer Variable:

    <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>

Rufen Sie dann das Makro wie folgt auf:

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

Der obige Code verwendet Javascript Split und Join, was schneller als Regex ist. "lokale" Eigenschaften werden an JavaScript übergeben, sodass keine Eigenschaften verloren gehen.

River Rock
quelle
0

Oder ... Sie können es auch versuchen Ihre eigene Aufgabe

JAVA CODE:

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..

ANT SCRIPT

...
<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>

KONSOLE:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
samuelbravolopez
quelle