Substituindo caracteres na propriedade Ant

90

Existe uma maneira simples de pegar o valor de uma propriedade e depois copiá-lo para outra propriedade com certos caracteres substituídos?

Diga propA=This is a value. Quero substituir todos os espaços em sublinhados, resultando em propB=This_is_a_value.

aberrante 80
fonte

Respostas:

89

Use a tarefa propertyregex do Ant Contrib .

Eu acho que você quer:

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

Infelizmente, os exemplos dados não são muito claros, mas vale a pena tentar. Você também deve verificar o que acontece se não houver sublinhados - talvez seja necessário usar a defaultValueopção também.

Jon Skeet
fonte
3
Adicionar defaultValue="${propA}"é perfeito como uma busca / substituição geral de uma linha: caso contrário, se não houver correspondência, nada é colocado no propB !! Obrigado!
David Robson
107

Aqui está a solução sem scripts e sem jars externos como o ant-conrib:

O truque é usar os recursos da ANT:

  • Há um tipo de recurso chamado "propertyresource" que é como um arquivo de origem, mas fornece um fluxo do valor da string deste recurso. Então você pode carregá-lo e usá-lo em qualquer tarefa como "copiar" que aceita arquivos
  • Também existe a tarefa "loadresource" que pode carregar qualquer recurso para uma propriedade (por exemplo, um arquivo), mas esta também pode carregar nosso propertyresource. Esta tarefa permite filtrar a entrada aplicando algumas transformações de token. Finalmente, o seguinte fará o que você quiser:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Este substituirá todos os "" em propA por "_" e colocará o resultado em propB. "filetokenizer" trata todo o fluxo de entrada (nossa propriedade) como um token e aplica a substituição da string nele.

Você pode fazer outras transformações sofisticadas usando outros filtros de token: http://ant.apache.org/manual/Types/filterchain.html

Uwe Schindler
fonte
7
Obrigado! Acontece que você pode até largar o <filetokenizer/>bit. Seu código funciona bem sem ele (pelo menos no Ant v1.8.3).
Matthias
Se você estiver tentando fazer isso de dentro do Maven, consulte stackoverflow.com/a/22969187/2163960
user2163960
3
Vote positivamente para uma técnica que funciona no vanilla ante não requer bibliotecas adicionais.
Christopher Schultz
57

Se ant-contrib não for uma opção, aqui está uma solução portátil para Java 1.6 e 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
fonte
6
Se este método for usado, seria bom incluir o script em CDATA para evitar problemas com a análise xml. <script language = "javascript"> <! [CDATA [// o código de script java pode usar com segurança o caractere '<'. ]]> </script>
Jan Arciuchiewicz
3
@dnault Javascript não tem uma replaceAllfunção para strings. Use em seu before.replace( /\s/g, "_" )lugar.
Larry Battle
3
@LarryBattle project.getProperty()retorna um java.lang.String, então replaceAll()é apropriado neste caso. Se você quiser usar replace(), poderá converter 'antes' em uma string JavaScript nativa com:before = new String(before);
dnault
1
project.setNewPropertyseria mais portátil, pois setPropertypoderia substituir o valor da propriedade antiga. Pode até escrever para a beforepropriedade.
Jarekczek,
Requer Rhino
vintproykt
26

Caso você queira uma solução que use apenas recursos integrados do Ant , considere o seguinte:

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

A saída é ${propB} = "This_is_a_value"

mgaert
fonte
2
Quem limpa some.tmp.file?
ceving
Já que outras pessoas podem querer usar isso; Adicione <delete file = "some.tmp.file" /> após </loadfile>. Respostas @ceving Question :)
terix2k11
8

Use algum aplicativo externo como sed:

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

Se você executar o Windows, procure por "gnuwin32 sed" no Google.

O comando s/_/./gsubstitui todos _por . Este script funciona bem no Windows. No Linux, o arg pode precisar ser citado.

Jarekczek
fonte
8

Duas possibilidades:

via tarefa de script e mecanismo javascript embutido (se estiver usando 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 usando 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>

para substituir a propriedade propA existente, basta substituir propB por propA

Rebse
fonte
7

Aqui está uma versão mais generalizada da resposta de Uwe Schindler :

Você pode usar um macrodefpara criar uma tarefa 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>

você pode usar isso da seguinte maneira:

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

isso será muito útil se você estiver fazendo isso várias vezes

Avinash R
fonte
3

Adicionando um exemplo de resposta mais completo sobre uma resposta anterior

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

Apenas um FYI para a resposta Substituindo caracteres na propriedade Ant - se você está tentando usar isso dentro de uma execução maven, você não pode referenciar variáveis ​​maven diretamente. Você precisará de algo assim:

...
<target>
<property name="propATemp" value="${propA}"/>
    <loadresource property="propB">
    <propertyresource name="propATemp" />
...
user2163960
fonte
Que partes relacionadas com a substituição " "de "_"?
Jin Kwon
Alternativamente, em maven, você pode evitar a necessidade de usar a propriedade propATemp substituindo <propertyresource name="propATemp"/>por<string value="${propA}"/>
Ed Randall
1

As propriedades não podem ser alteradas, mas antContrib vars ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) pode.

Aqui está uma macro para localizar / substituir em uma 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>

Em seguida, chame a macro como:

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

O código acima usa javascript split then join, que é mais rápido que regex. As propriedades "locais" são passadas para o JavaScript para que não haja vazamento de propriedade.

River Rock
fonte
0

Ou ... Você também pode tentar sua própria tarefa

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>

CONSOLE:

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