Remplacement de caractères dans la propriété Ant

90

Existe-t-il un moyen simple de prendre la valeur d'une propriété et de la copier dans une autre propriété en remplaçant certains caractères?

Dis propA=This is a value. Je veux remplacer tous les espaces qu'il contient par des traits de soulignement, ce qui entraîne propB=This_is_a_value.

aberrant80
la source

Réponses:

89

Utilisez la tâche propertyregex d' Ant Contrib .

Je pense que tu veux:

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

Malheureusement, les exemples donnés ne sont pas très clairs, mais cela vaut la peine d'essayer. Vous devriez également vérifier ce qui se passe s'il n'y a pas de traits de soulignement - vous devrez peut-être également utiliser l' defaultValueoption.

Jon Skeet
la source
3
L'ajout defaultValue="${propA}"est parfait en tant que recherche générale / remplacement d'une seule ligne: sinon, s'il n'y a pas de correspondance, rien n'est mis dans propB !! Merci!
David Robson
107

Voici la solution sans script et sans jars externes comme ant-conrib:

L'astuce consiste à utiliser les ressources d'ANT:

  • Il existe un type de ressource appelé "propertyresource" qui ressemble à un fichier source, mais fournit un flux à partir de la valeur de chaîne de cette ressource. Vous pouvez donc le charger et l'utiliser dans n'importe quelle tâche comme "copier" qui accepte des fichiers
  • Il y a aussi la tâche "loadresource" qui peut charger n'importe quelle ressource dans une propriété (par exemple, un fichier), mais celle-ci pourrait aussi charger notre propriété. Cette tâche permet de filtrer l'entrée en appliquant certaines transformations de jetons. Enfin, ce qui suit fera ce que vous voulez:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Celui-ci remplacera tous les "" de propA par "_" et placera le résultat dans propB. "filetokenizer" traite tout le flux d'entrée (notre propriété) comme un jeton et y ajoute le remplacement de chaîne.

Vous pouvez faire d'autres transformations sophistiquées en utilisant d'autres filtres de jetons: http://ant.apache.org/manual/Types/filterchain.html

Uwe Schindler
la source
7
Merci! Il s'avère que vous pouvez même laisser tomber le <filetokenizer/>bit. Votre code fonctionne bien sans lui (au moins sur Ant v1.8.3).
Matthias
Si vous essayez de le faire depuis Maven, consultez stackoverflow.com/a/22969187/2163960
user2163960
3
Votez pour une technique qui fonctionne à la vanille antet ne nécessite pas de bibliothèques supplémentaires.
Christopher Schultz
57

Si ant-contrib n'est pas une option, voici une solution portable pour Java 1.6 et versions ultérieures:

<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
la source
6
Si ce metod est utilisé, il serait bon d'inclure le script dans CDATA pour éviter des problèmes avec l'analyse XML. <script language = "javascript"> <! [CDATA [// code de script java peut utiliser en toute sécurité le caractère '<'. ]]> </script>
Jan Arciuchiewicz
3
@dnault Javascript n'a pas de replaceAllfonction pour les chaînes. Utilisez before.replace( /\s/g, "_" )plutôt.
Larry Battle
3
@LarryBattle project.getProperty()renvoie a java.lang.String, c'est donc replaceAll()approprié dans ce cas. Si vous souhaitez utiliser replace(), vous pouvez convertir «avant» en une chaîne JavaScript native avec:before = new String(before);
dnault
1
project.setNewPropertyserait plus portable, tout comme setPropertypourrait remplacer l'ancienne valeur de propriété. Il pourrait même écrire à la beforepropriété.
Jarekczek
Il nécessite Rhino
vintproykt le
26

Si vous voulez une solution qui ne utilise Ant ENCASTRÉS seulement , considérez ceci:

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

La sortie est ${propB} = "This_is_a_value"

mgaert
la source
2
Qui nettoie certains fichiers.tmp?
ceving
Puisque d'autres pourraient vouloir utiliser ceci; Ajoutez <delete file = "some.tmp.file" /> après </loadfile>. Answers @ceving Question :)
terix2k11
8

Utilisez une application externe comme sed:

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

Si vous exécutez Windows, recherchez "gnuwin32 sed" sur Google.

La commande s/_/./gremplace tout _par . Ce script va bien sous windows. Sous Linux, arg peut avoir besoin de citations.

Jarekczek
la source
8

Deux possibilités:

via une tâche de script et un moteur javascript intégré (si vous utilisez 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>

ou en utilisant l' addon 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>

pour écraser la propriété existante propA, remplacez simplement propB par propA

Rebse
la source
7

Voici une version plus générale de la réponse d' Uwe Schindler :

Vous pouvez utiliser a macrodefpour créer une tâche personnalisée.

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

vous pouvez l'utiliser comme suit:

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

cela sera très utile si vous faites cela plusieurs fois

Avinash R
la source
3

Ajout d'un exemple de réponse plus complet par rapport à une réponse précédente

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

Juste un FYI pour réponse Remplacement des caractères dans la propriété Ant - si vous essayez d'utiliser cela dans une exécution maven, vous ne pouvez pas référencer directement les variables maven. Vous aurez besoin de quelque chose comme ceci:

...
<target>
<property name="propATemp" value="${propA}"/>
    <loadresource property="propB">
    <propertyresource name="propATemp" />
...
user2163960
la source
Quelles parties liées au remplacement " "de "_"?
Jin Kwon
Alternativement dans maven, vous pouvez éviter le besoin d'utiliser la propriété propATemp en remplaçant <propertyresource name="propATemp"/>par<string value="${propA}"/>
Ed Randall
1

Les propriétés ne peuvent pas être modifiées, mais les variables antContrib ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) le peuvent.

Voici une macro pour faire une recherche / remplacement sur un 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>

Appelez ensuite la macro comme:

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

Le code ci-dessus utilise javascript split puis join, ce qui est plus rapide que regex. Les propriétés "locales" sont transmises à JavaScript donc aucune fuite de propriété.

River Rock
la source
0

Ou ... vous pouvez également essayer votre propre tâche

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

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>

CONSOLE:

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