Reemplazo de caracteres en la propiedad Ant

90

¿Existe una forma sencilla de tomar el valor de una propiedad y luego copiarlo en otra propiedad con ciertos caracteres reemplazados?

Decir propA=This is a value. Quiero reemplazar todos los espacios en guiones bajos, lo que da como resultado propB=This_is_a_value.

aberrante80
fuente

Respuestas:

89

Utilice la tarea propertyregex de Ant Contrib .

Creo que quieres:

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

Desafortunadamente, los ejemplos dados no son muy claros, pero vale la pena intentarlo. También debe verificar qué sucede si no hay guiones bajos; es posible que también deba usar la defaultValueopción.

Jon Skeet
fuente
3
Agregar defaultValue="${propA}"es perfecto como búsqueda general / reemplazo de una sola línea: de lo contrario, si no hay coincidencia, no se agrega nada en propB. ¡Gracias!
David Robson
107

Aquí está la solución sin secuencias de comandos y sin frascos externos como ant-conrib:

El truco consiste en utilizar los recursos de ANT:

  • Hay un tipo de recurso llamado "propertyresource" que es como un archivo fuente, pero proporciona una secuencia del valor de cadena de este recurso. Para que pueda cargarlo y usarlo en cualquier tarea como "copiar" que acepta archivos
  • También existe la tarea "loadresource" que puede cargar cualquier recurso en una propiedad (por ejemplo, un archivo), pero este también podría cargar nuestro recurso de propiedad. Esta tarea permite filtrar la entrada aplicando algunas transformaciones de token. Finalmente lo siguiente hará lo que quieras:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Este reemplazará todo "" en propA por "_" y colocará el resultado en propB. "filetokenizer" trata todo el flujo de entrada (nuestra propiedad) como un token y aplica el reemplazo de cadena en él.

Puede hacer otras transformaciones sofisticadas utilizando otros filtros de token: http://ant.apache.org/manual/Types/filterchain.html

Uwe Schindler
fuente
7
¡Gracias! Resulta que incluso puedes soltar el <filetokenizer/>bit. Su código funciona bien sin él (al menos en Ant v1.8.3).
Matthias
Si está intentando hacer esto desde Maven, consulte stackoverflow.com/a/22969187/2163960
user2163960
3
Vota a favor de una técnica que funciona en vainilla anty no requiere bibliotecas adicionales.
Christopher Schultz
57

Si ant-contrib no es una opción, aquí hay una solución portátil para Java 1.6 y posterior:

<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
fuente
6
Si se utiliza este método, sería bueno incluir el script en CDATA para evitar problemas con el análisis de XML. <script language = "javascript"> <! [CDATA [// El código de script java puede usar el carácter '<' de forma segura. ]]> </script>
Jan Arciuchiewicz
3
@dnault Javascript no tiene una replaceAllfunción para cadenas. Úselo en su before.replace( /\s/g, "_" )lugar.
Larry Battle
3
@LarryBattle project.getProperty()devuelve un java.lang.String, por lo que replaceAll()es apropiado en este caso. Si quisiera usar replace(), podría convertir 'antes' a una cadena de JavaScript nativa con:before = new String(before);
dnault
1
project.setNewPropertysería más portátil, ya que setPropertypodría sobrescribir el valor de la propiedad anterior. Incluso podría escribir a la beforepropiedad.
Jarekczek
Requiere Rhino
vintproykt
26

En caso de que desee una solución que utilice solo elementos integrados de Ant , considere esto:

<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 salida es ${propB} = "This_is_a_value"

mgaert
fuente
2
¿Quién limpia algún archivo.tmp?
hasta el
Dado que otros pueden querer usar esto; Agregue <delete file = "some.tmp.file" /> después de </loadfile>. Respuestas @ceving Question :)
terix2k11
8

Use alguna aplicación externa como sed:

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

Si ejecuta Windows, búsquelo en Google para "gnuwin32 sed".

El comando s/_/./greemplaza todos _con . Este script funciona bien en Windows. En linux arg puede ser necesario citar.

Jarekczek
fuente
8

Dos posibilidades:

a través de la tarea de script y el motor javascript incorporado (si usa 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 el complemento 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>

para sobrescribir la propiedad existente propA simplemente reemplace propB con propA

Rebse
fuente
7

Aquí hay una versión más generalizada de la respuesta de Uwe Schindler :

Puede utilizar a macrodefpara crear una tarea personalizada.

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

puede usar esto de la siguiente manera:

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

esto será bastante útil si lo haces varias veces

Avinash R
fuente
3

Agregar una respuesta un ejemplo más completo sobre una respuesta anterior

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

Solo un FYI para la respuesta Reemplazo de caracteres en la propiedad Ant : si está tratando de usar esto dentro de una ejecución maven, no puede hacer referencia a las variables maven directamente. Necesitará algo como esto:

...
<target>
<property name="propATemp" value="${propA}"/>
    <loadresource property="propB">
    <propertyresource name="propATemp" />
...
usuario2163960
fuente
¿Qué partes relacionadas con la sustitución " "de "_"?
Jin Kwon
Alternativamente, en maven, puede evitar la necesidad de usar la propiedad propATemp reemplazando <propertyresource name="propATemp"/>con<string value="${propA}"/>
Ed Randall
1

Las propiedades no se pueden cambiar, pero antContrib vars ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) sí.

Aquí hay una macro para hacer una búsqueda / reemplazo en 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>

Luego llame a la macro como:

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

El código anterior usa javascript dividir y luego unirse, que es más rápido que las expresiones regulares. Las propiedades "locales" se pasan a JavaScript para que no se produzcan fugas de propiedad.

River Rock
fuente
0

O ... también puede probar su propia tarea

CÓDIGO 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>

CONSOLA:

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