การแทนที่อักขระในคุณสมบัติ Ant


90

มีวิธีง่ายๆในการรับค่าของคุณสมบัติแล้วคัดลอกไปยังคุณสมบัติอื่นโดยแทนที่อักขระบางตัวหรือไม่?

พูดpropA=This is a value. propB=This_is_a_valueฉันต้องการที่จะแทนที่ช่องว่างทั้งหมดในนั้นเข้าไปในขีดที่เกิดใน

คำตอบ:


89

ใช้propertyregexงานจากมด Contrib

ฉันคิดว่าคุณต้องการ:

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

น่าเสียดายที่ตัวอย่างที่ให้มานั้นไม่ชัดเจนมากนัก แต่ก็คุ้มค่าที่จะลองดู คุณควรตรวจสอบสิ่งที่เกิดขึ้นหากไม่มีเครื่องหมายขีดล่าง - คุณอาจต้องใช้defaultValueตัวเลือกนี้ด้วย


3
การเพิ่มdefaultValue="${propA}"นั้นสมบูรณ์แบบเหมือนการค้นหาทั่วไป / แทนที่ one-liner มิฉะนั้นหากไม่มีการจับคู่จะไม่มีอะไรใส่ propB !! ขอบคุณ!
David Robson

107

นี่คือวิธีแก้ปัญหาโดยไม่ต้องเขียนสคริปต์และไม่มีขวดภายนอกเช่น ant-conrib:

เคล็ดลับคือการใช้ทรัพยากรของ ANT:

  • มีทรัพยากรประเภทหนึ่งที่เรียกว่า "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)
Matthias

หากคุณกำลังพยายามดำเนินการจากภายใน Maven โปรดดูstackoverflow.com/a/22969187/2163960
user2163960

3
โหวตให้เทคนิคที่ใช้ได้กับวานิลลาantและไม่ต้องใช้ไลบรารีเพิ่มเติม
Christopher Schultz

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
หากใช้ metod นี้การใส่สคริปต์ใน CDATA จะเป็นการดีเพื่อหลีกเลี่ยงปัญหาในการแยกวิเคราะห์ xml <script language = "javascript"> <! [CDATA [// รหัสสคริปต์ java สามารถใช้อักขระ '<' ได้อย่างปลอดภัย ]]> </script>
Jan Arciuchiewicz

3
@dnault Javascript ไม่มี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คุณสมบัติ
Jarekczek

ต้องใช้แรด
vintproykt

26

ในกรณีที่คุณต้องการโซลูชันที่ใช้ Ant built-in เท่านั้นให้พิจารณาสิ่งนี้:

<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 :)
terix2k11

8

ใช้แอปภายนอกเช่น sed:

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

หากคุณเรียกใช้ Windows ให้ใช้ googling สำหรับ "gnuwin32 sed"

คำสั่งs/_/./gแทนที่ทุก_ด้วย. สคริปต์นี้ทำงานได้ดีภายใต้หน้าต่าง ภายใต้อาร์กิวเมนต์ลินุกซ์อาจต้องมีการอ้างอิง


8

ความเป็นไปได้สองประการ:

ผ่านงานสคริปต์และเอ็นจิ้นจาวาสคริปต์ในตัว (หากใช้ 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

นี่คือคำตอบของUwe Schindler ในเวอร์ชันทั่วไป :

คุณสามารถใช้ 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="_"/>

สิ่งนี้จะมีประโยชน์มากหากคุณทำหลาย ๆ ครั้ง



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}"/>
Ed Randall

1

คุณสมบัติไม่สามารถเปลี่ยนแปลงได้ แต่เป็นตัวแทนของ antContrib ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) สามารถ

นี่คือมาโครสำหรับค้นหา / แทนที่ใน 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>

จากนั้นเรียกมาโครเช่น:

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

โค้ดด้านบนใช้การแยกจาวาสคริปต์แล้วเข้าร่วมซึ่งเร็วกว่า regex คุณสมบัติ "local" จะถูกส่งต่อไปยัง JavaScript ดังนั้นจึงไม่มีการรั่วไหลของคุณสมบัติ


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.