Sostituzione dei caratteri nella proprietà Ant


90

Esiste un modo semplice per prendere il valore di una proprietà e poi copiarlo in un'altra proprietà sostituendo determinati caratteri?

propA=This is a value. Voglio sostituire tutti gli spazi in esso con trattini bassi, risultando in propB=This_is_a_value.

Risposte:


89

Usa l' attività propertyregex di Ant Contrib .

Penso che tu voglia:

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

Sfortunatamente gli esempi forniti non sono molto chiari, ma vale la pena provarli. Dovresti anche controllare cosa succede se non ci sono trattini bassi: potresti dover usare anche l' defaultValueopzione.


3
L'aggiunta defaultValue="${propA}"è perfetta come ricerca / sostituzione generale di una riga: altrimenti, se non c'è corrispondenza, non viene messo nulla in propB !! Grazie!
David Robson

107

Ecco la soluzione senza script e senza barattoli esterni come ant-conrib:

Il trucco sta nell'utilizzare le risorse di ANT:

  • Esiste un tipo di risorsa chiamato "propertyresource" che è come un file di origine, ma fornisce un flusso dal valore stringa di questa risorsa. Quindi puoi caricarlo e usarlo in qualsiasi attività come "copia" che accetta file
  • C'è anche il task "loadresource" che può caricare qualsiasi risorsa su una proprietà (ad esempio, un file), ma questa potrebbe anche caricare la nostra propertyresource. Questa attività consente di filtrare l'input applicando alcune trasformazioni di token. Infine il seguente farà quello che vuoi:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Questo sostituirà tutto "" in propA con "_" e posizionerà il risultato in propB. "filetokenizer" tratta l'intero flusso di input (nostra proprietà) come un token e applica la sostituzione della stringa su di esso.

Puoi fare altre trasformazioni fantasiose usando altri filtri token: http://ant.apache.org/manual/Types/filterchain.html


7
Grazie! Si scopre che puoi anche lasciare il <filetokenizer/>bit. Il tuo codice funziona bene senza di esso (almeno su Ant v1.8.3).
Matthias,

Se si sta cercando di fare questo dall'interno di Maven, vedere stackoverflow.com/a/22969187/2163960
user2163960

3
Upvote per una tecnica che funziona in vaniglia ante non richiede librerie aggiuntive.
Christopher Schultz

57

Se ant-contrib non è un'opzione, ecco una soluzione portatile per Java 1.6 e versioni successive:

<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
Se si utilizza questo metodo, sarebbe bene racchiudere lo script in CDATA per evitare problemi con l'analisi xml. <script language = "javascript"> <! [CDATA [// codice java script può tranquillamente utilizzare il carattere "<". ]]> </script>
Jan Arciuchiewicz

3
@dnault Javascript non ha una replaceAllfunzione per le stringhe. Usa before.replace( /\s/g, "_" )invece.
Larry Battle

3
@LarryBattle project.getProperty()restituisce a java.lang.String, quindi replaceAll()è appropriato in questo caso. Se si desidera utilizzare replace(), è possibile convertire "prima" in una stringa JavaScript nativa con:before = new String(before);
dnault

1
project.setNewPropertysarebbe più portabile, in quanto setPropertypotrebbe sovrascrivere il vecchio valore della proprietà. Potrebbe anche scrivere alla beforeproprietà.
Jarekczek

Richiede Rhino
vintproykt

26

Nel caso in cui desideri una soluzione che utilizzi solo i built-in Ant , considera questo:

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

L'output è ${propB} = "This_is_a_value"


2
Chi pulisce alcuni.tmp.file?
Ceving

Poiché altri potrebbero volerlo utilizzare; Aggiungi <delete file = "some.tmp.file" /> dopo </loadfile>. Answers @ceving Question :)
terix2k11

8

Usa alcune app esterne come sed:

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

Se esegui Windows, cercalo su Google per "gnuwin32 sed".

Il comando s/_/./gsostituisce ogni _con . Questo script va bene sotto Windows. Sotto linux arg potrebbe aver bisogno di virgolette.


8

Due possibilità:

tramite attività di script e motore javascript integrato (se si utilizza 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>

o usando l' addon di 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>

per sovrascrivere la proprietà esistente propA è sufficiente sostituire propB con propA


7

Ecco una versione più generalizzata della risposta di Uwe Schindler :

È possibile utilizzare a macrodefper creare un'attività personalizzata.

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

puoi usarlo come segue:

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

questo sarà molto utile se lo fai più volte


3

Aggiunta di una risposta esempio più completo rispetto a una risposta precedente

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

1

Solo un FYI per la risposta Sostituzione dei caratteri nella proprietà Ant : se stai cercando di usarlo all'interno di un'esecuzione Maven, non puoi fare riferimento direttamente a variabili Maven. Avrai bisogno di qualcosa del genere:

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

Quali parti relative a sostituire " "a "_"?
Jin Kwon

In alternativa in Maven, potresti evitare la necessità di utilizzare la proprietà propATemp sostituendo <propertyresource name="propATemp"/>con<string value="${propA}"/>
Ed Randall

1

Le proprietà non possono essere modificate ma antContrib vars ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) sì .

Ecco una macro per eseguire una ricerca / sostituzione su una 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>

Quindi chiama la macro come:

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

Il codice sopra usa javascript split then join, che è più veloce di regex. Le proprietà "locali" vengono passate a JavaScript quindi nessuna perdita di proprietà.


0

Oppure ... Puoi anche provare il tuo compito

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

SCRIPT ANT

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

CONSOLLE:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.