Mengganti karakter di properti Ant

90

Adakah cara sederhana untuk mengambil nilai sebuah properti dan kemudian menyalinnya ke properti lain dengan mengganti karakter tertentu?

Katakan propA=This is a value. Saya ingin mengganti semua spasi di dalamnya menjadi garis bawah, menghasilkan propB=This_is_a_value.

aberrant80
sumber

Jawaban:

89

Gunakan tugas propertyregex dari Ant Contrib .

Saya pikir Anda ingin:

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

Sayangnya contoh yang diberikan tidak terlalu jelas, tetapi patut dicoba. Anda juga harus memeriksa apa yang terjadi jika tidak ada garis bawah - Anda mungkin perlu menggunakan defaultValueopsi ini juga.

Jon Skeet
sumber
3
Menambahkan defaultValue="${propA}"sempurna sebagai pencarian umum / ganti satu baris: jika tidak, jika tidak ada yang cocok, tidak ada yang dimasukkan ke propB !! Terima kasih!
David Robson
107

Berikut solusinya tanpa scripting dan tidak ada stoples eksternal seperti ant-conrib:

Triknya adalah dengan menggunakan sumber daya ANT:

  • Ada satu jenis sumber daya yang disebut "propertyresource" yang seperti file sumber, tetapi menyediakan aliran dari nilai string sumber daya ini. Jadi Anda dapat memuatnya dan menggunakannya dalam tugas apa pun seperti "salin" yang menerima file
  • Ada juga tugas "loadresource" yang dapat memuat sumber daya apa pun ke properti (misalnya, file), tetapi tugas ini juga dapat memuat sumber daya properti kita. Tugas ini memungkinkan pemfilteran input dengan menerapkan beberapa transformasi token. Akhirnya yang berikut ini akan melakukan apa yang Anda inginkan:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Yang ini akan mengganti semua "" di propA dengan "_" dan menempatkan hasilnya di propB. "filetokenizer" memperlakukan seluruh aliran input (properti kami) sebagai satu token dan menerapkan penggantian string di atasnya.

Anda dapat melakukan transformasi mewah lainnya menggunakan tokenfilters lain: http://ant.apache.org/manual/Types/filterchain.html

Uwe Schindler
sumber
7
Terima kasih! Ternyata Anda bahkan bisa menjatuhkannya <filetokenizer/>sedikit. Kode Anda berfungsi dengan baik tanpanya (setidaknya di Ant v1.8.3).
Matthias
Jika Anda mencoba melakukan ini dari dalam Maven, lihat stackoverflow.com/a/22969187/2163960
user2163960
3
Beri suara positif untuk teknik yang berfungsi di vanilla antdan tidak memerlukan pustaka tambahan.
Christopher Schultz
57

Jika ant-contrib bukan pilihan, berikut adalah solusi portabel untuk Java 1.6 dan yang lebih baru:

<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
sumber
6
Jika metode ini digunakan, alangkah baiknya untuk menyertakan skrip dalam CDATA untuk menghindari masalah dengan penguraian xml. <script language = "javascript"> <! [CDATA [// kode java script dapat menggunakan karakter '<' dengan aman. ]]> </script>
Jan Arciuchiewicz
3
@dnault Javascript tidak memiliki replaceAllfungsi untuk string. Gunakan before.replace( /\s/g, "_" )sebagai gantinya.
Larry Battle
3
@LarryBattle project.getProperty()mengembalikan a java.lang.String, jadi replaceAll()cocok dalam kasus ini. Jika Anda ingin menggunakan replace(), Anda dapat mengonversi 'sebelum' menjadi string JavaScript asli dengan:before = new String(before);
dnault
1
project.setNewPropertyakan lebih portabel, karena setPropertydapat menimpa nilai properti lama. Ia bahkan bisa menulis ke beforeproperti.
Jarekczek
Dibutuhkan Rhino
vintproykt
26

Jika anda ingin solusi yang tidak menggunakan Ant built-in hanya , pertimbangkan ini:

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

Outputnya adalah ${propB} = "This_is_a_value"

mgaert
sumber
2
Siapa yang membersihkan some.tmp.file?
ceving
Karena orang lain mungkin ingin menggunakan ini; Tambahkan <delete file = "some.tmp.file" /> setelah </loadfile>. Jawaban @ceving Pertanyaan :)
terix2k11
8

Gunakan beberapa aplikasi eksternal seperti sed:

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

Jika Anda menjalankan Windows, dapatkan itu googling untuk "gnuwin32 sed".

Perintah s/_/./gmenggantikan setiap _dengan . Skrip ini berjalan dengan baik di bawah jendela. Di bawah linux arg mungkin perlu kutipan.

Jarekczek
sumber
8

Dua kemungkinan:

melalui tugas skrip dan mesin javascript bawaan (jika menggunakan 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>

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

untuk menimpa properti propA yang ada cukup ganti propB dengan propA

Rebse
sumber
7

Berikut adalah versi jawaban Uwe Schindler yang lebih umum :

Anda dapat menggunakan a macrodefuntuk membuat tugas kustom.

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

Anda dapat menggunakan ini sebagai berikut:

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

ini akan sangat berguna jika Anda melakukan ini beberapa kali

Avinash R
sumber
3

Menambahkan contoh jawaban yang lebih lengkap dari jawaban sebelumnya

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

Hanya FYI untuk jawaban Mengganti karakter di properti Ant - jika Anda mencoba menggunakan ini di dalam eksekusi maven, Anda tidak dapat mereferensikan variabel maven secara langsung. Anda akan membutuhkan sesuatu seperti ini:

...
<target>
<property name="propATemp" value="${propA}"/>
    <loadresource property="propB">
    <propertyresource name="propATemp" />
...
pengguna2163960
sumber
Bagian apa yang terkait dengan mengganti " "ke "_"?
Jin Kwon
Atau di maven, Anda dapat menghindari kebutuhan untuk menggunakan properti propATemp dengan mengganti <propertyresource name="propATemp"/>dengan<string value="${propA}"/>
Ed Randall
1

Properti tidak dapat diubah tetapi vars antContrib ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) bisa.

Berikut adalah makro untuk melakukan pencarian / penggantian pada 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>

Kemudian panggil makro seperti:

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

Kode di atas menggunakan javascript split kemudian join, yang lebih cepat dari regex. properti "lokal" diteruskan ke JavaScript sehingga tidak ada kebocoran properti.

River Rock
sumber
0

Atau ... Anda juga dapat mencoba Tugas Anda Sendiri

KODE JAWA:

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

SKRIP SEMUT

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

MENGHIBUR:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
samuelbravolopez.dll
sumber