Замена символов в свойстве Ant

90

Есть ли простой способ взять значение свойства, а затем скопировать его в другое свойство с заменой определенных символов?

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

аберрантный80
источник

Ответы:

89

Используйте задачу propertyregex из Ant Contrib .

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

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

К сожалению, приведенные примеры не очень понятны, но попробовать стоит. Вы также должны проверить, что происходит, если нет никаких подчеркиваний - вам также может потребоваться использовать эту defaultValueопцию.

Джон Скит
источник
3
Добавление defaultValue="${propA}"идеально подходит для обычного поиска / замены однострочника: в противном случае, если совпадений нет, в propB ничего не помещается !! Благодарность!
Дэвид Робсон
107

Вот решение без сценариев и внешних банок, таких как ant-conrib:

Уловка состоит в том, чтобы использовать ресурсы ANT:

  • Существует один тип ресурса, называемый «propertyresource», который похож на исходный файл, но предоставляет поток из строкового значения этого ресурса. Таким образом, вы можете загрузить его и использовать в любой задаче, например, «копировать», которая принимает файлы.
  • Также существует задача loadresource, которая может загружать любой ресурс в свойство (например, файл), но это также может загрузить наш propertyresource. Эта задача позволяет фильтровать ввод, применяя некоторые преобразования токенов. Наконец, следующее будет делать то, что вы хотите:
<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).
Matthias
Если вы пытаетесь сделать это изнутри 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>
dnault
источник
6
Если используется этот метод, было бы хорошо заключить скрипт в CDATA, чтобы избежать проблем с синтаксическим анализом xml. <script language = "javascript"> <! [CDATA [// код java-скрипта может безопасно использовать символ '<'. ]]> </script>
Ян Арчюшевич
3
@dnault Javascript не имеет replaceAllфункции для строк. before.replace( /\s/g, "_" )Вместо этого используйте .
Ларри Бэттл,
3
@LarryBattle project.getProperty()возвращает a java.lang.String, поэтому replaceAll()в этом случае подходит. Если вы хотите использовать replace(), вы можете преобразовать «до» в собственную строку JavaScript с помощью:before = new String(before);
dnault
1
project.setNewPropertyбудет более портативным, так как setPropertyможет перезаписать старое значение свойства. Он мог даже написать в beforeсобственность.
Ярекчек
Требуется Rhino
винтпройт
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"

Mgaert
источник
2
Кто чистит some.tmp.file?
ceving
Поскольку другие могут захотеть использовать это; Добавьте <delete file = "some.tmp.file" /> после </loadfile>. Answers @ceving Question :)
terix2k11
8

Используйте какое-нибудь внешнее приложение, например sed:

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

Если вы запустите Windows, поищите в Google "gnuwin32 sed".

Команда s/_/./gзаменяет каждый _на . Этот сценарий хорошо работает под окнами. В 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>

или используя 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>

чтобы перезаписать существующее свойство propA, просто замените propB на propA

Ребсе
источник
7

Вот более обобщенная версия ответа Уве Шиндлера :

Вы можете использовать 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" />
...
user2163960
источник
Какие части , связанные с заменой " "на "_"?
Джин Квон
В качестве альтернативы в 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, а затем соединение, что быстрее, чем регулярное выражение. "локальные" свойства передаются в JavaScript, поэтому утечки свойств не происходит.

River Rock
источник
0

Или ... Вы также можете попробовать свою задачу

КОД 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>

ПРИСТАВКА:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
Самуэльбраволопес
источник