Заміна символів у властивості Ant


90

Чи існує простий спосіб визначити вартість властивості, а потім скопіювати її в іншу властивість із заміненими певними символами?

Say propA=This is a value. Я хочу замінити всі пробіли в ньому на підкреслення, в результаті чого propB=This_is_a_value.

Відповіді:


89

Використовуйте завдання propertyregex від Ant Contrib .

Я думаю, ви хочете:

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

На жаль, наведені приклади не дуже зрозумілі, але варто спробувати це. Ви також повинні перевірити, що відбувається, якщо немає підкреслення - можливо, вам також доведеться скористатися defaultValueопцією.


3
Додавання defaultValue="${propA}"ідеально підходить для загального пошуку / заміни однокласника: інакше, якщо збігу немає, нічого не вставляється в propB !! Дякую!
Девід Робсон,

107

Ось рішення без сценаріїв і відсутність зовнішніх банок, таких як ant-conrib:

Фокус полягає у використанні ресурсів АНТ:

  • Існує один тип ресурсу під назвою "propertyresource", який схожий на вихідний файл, але забезпечує потік із рядкового значення цього ресурсу. Таким чином, ви можете завантажити його та використовувати в будь-якому завданні, наприклад "копію", яке приймає файли
  • Існує також завдання "loadresource", яке може завантажити будь-який ресурс у властивість (наприклад, файл), але це також може завантажити наш ресурс ресурсу. Це завдання дозволяє фільтрувати вхідні дані, застосовуючи деякі перетворення лексем. Нарешті, наступне зробить те, що ви хочете:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Цей замінить усі "" в propA на "_" і помістить результат у propB. "filetokenizer" трактує весь вхідний потік (наше властивість) як один маркер і застосовує заміну рядка на ньому.

Ви можете зробити інші химерні перетворення, використовуючи інші токенфільтри: http://ant.apache.org/manual/Types/filterchain.html


7
Дякую! Виявляється, ви можете навіть скинути <filetokenizer/>біт. Ваш код чудово працює без нього (принаймні на Ant v1.8.3).
Маттіас

Якщо ви намагаєтеся зробити це зсередини Maven, см stackoverflow.com/a/22969187/2163960
user2163960

3
Проголосуйте за техніку, яка працює у ванілі antі не потребує додаткових бібліотек.
Крістофер Шульц,

57

Якщо ant-contrib не підходить, ось портативне рішення для Java 1.6 та пізніших версій:

<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
Якщо використовується цей метод, було б добре вкласти сценарій у CDATA, щоб уникнути проблем із синтаксичним розбором xml. <script language = "javascript"> <! [CDATA [// код сценарію Java може безпечно використовувати символ '<'. ]]> </script>
Ян Арцюхевич,

3
Javascript @dnault не має replaceAllфункції для рядків. Використовуйте before.replace( /\s/g, "_" )замість цього.
Larry Battle

3
@LarryBattle project.getProperty()повертає a java.lang.String, тому replaceAll()це доречно в цьому випадку. Якщо ви хочете використовувати replace(), ви можете перетворити 'before' у власний рядок JavaScript за допомогою:before = new String(before);
dnault

1
project.setNewPropertyбуде більш портативним, оскільки setPropertyможе перезаписати старе значення властивості. Можна навіть написати у beforeвласність.
Ярекчек

Для цього потрібен Rhino
vintproykt

26

У разі , якщо ви хочете , рішення , яке робить використання Ant вбудовані модулі тільки , вважають це:

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

Вихід є ${propB} = "This_is_a_value"


2
Хто чистить файл some.tmp.file?
заперечення

Оскільки інші можуть захотіти цим скористатися; Додайте <delete file = "some.tmp.file" /> після </loadfile>. Відповіді @ceving Question :)
terix2k11

8

Використовуйте якийсь зовнішній додаток, такий як sed:

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

Якщо ви запустите Windows, подивіться на "gnuwin32 sed".

Команда s/_/./gзамінює кожен _на . Цей сценарій добре працює під Windows. Під Linux arg може знадобитися цитування.


8

Дві можливості:

через завдання сценарію та вбудований механізм javascript (якщо використовується 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>

або за допомогою аддону Мурахи Флака

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

для перезапису існуючого властивості propA просто замініть propB на propA


7

Ось більш узагальнена версія відповіді Уве Шиндлера :

Ви можете використовувати a macrodefдля створення власного завдання.

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

Ви можете використовувати це наступним чином:

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

це буде дуже корисно, якщо ви робите це кілька разів


3

Додавання відповіді більш повний приклад порівняно з попередньою відповіддю

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

1

Просто FYI для відповіді Заміна символів у властивості Ant - якщо ви намагаєтесь використовувати це всередині виконання maven, ви не можете безпосередньо посилатися на змінні maven. Вам знадобиться щось подібне:

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

Які частини , пов'язані з заміною " "на "_"?
Jin Kwon

Як варіант у maven, ви можете уникнути необхідності використовувати майно propATemp , замінивши <propertyresource name="propATemp"/>на<string value="${propA}"/>
Ед Рендалл

1

Властивості не можна змінити, але antContrib варіюється ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ).

Ось макрос для пошуку / заміни змінної:

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

Потім викличте макрос так:

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

У наведеному вище коді використовується javascript split, а потім приєднання, що швидше, ніж регулярний вираз. "локальні" властивості передаються в JavaScript, тому відсутність витоку властивостей.


0

Або ... Ви також можете спробувати власне завдання

КОД ЯВИ:

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

АНТИЙНИЙ СЦЕНАРІЙ

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

КОНСОЛЬ:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.