Thay thế các ký tự trong thuộc tính Ant


90

Có cách nào đơn giản để lấy giá trị của một thuộc tính và sau đó sao chép nó sang một thuộc tính khác với các ký tự nhất định được thay thế không?

Nói đi propA=This is a value. Tôi muốn thay thế tất cả các khoảng trắng trong đó thành dấu gạch dưới, kết quả là propB=This_is_a_value.

Câu trả lời:


89

Sử dụng tác vụ propertyregex từ Ant Contrib .

Tôi nghĩ bạn muốn:

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

Thật không may, các ví dụ được đưa ra không quá rõ ràng, nhưng nó đáng để thử. Bạn cũng nên kiểm tra điều gì sẽ xảy ra nếu không có bất kỳ dấu gạch dưới nào - bạn cũng có thể cần sử dụng defaultValuetùy chọn này.


3
Thêm defaultValue="${propA}"là hoàn hảo như một tìm kiếm chung / thay thế một lớp lót: ngược lại, nếu không có kết quả phù hợp, không có gì được đưa vào propB !! Cảm ơn!
David Robson

107

Đây là giải pháp mà không cần tập lệnh và không có lọ bên ngoài như ant-conrib:

Bí quyết là sử dụng tài nguyên của ANT:

  • Có một loại tài nguyên được gọi là "propertyresource" giống như một tệp nguồn, nhưng cung cấp một luồng từ giá trị chuỗi của tài nguyên này. Vì vậy, bạn có thể tải nó và sử dụng nó trong bất kỳ tác vụ nào như "sao chép" chấp nhận tệp
  • Ngoài ra còn có tác vụ "loadresource" có thể tải bất kỳ tài nguyên nào vào một thuộc tính (ví dụ: một tệp), nhưng tác vụ này cũng có thể tải nguồn thuộc tính của chúng tôi. Tác vụ này cho phép lọc đầu vào bằng cách áp dụng một số chuyển đổi mã thông báo. Cuối cùng những điều sau sẽ làm những gì bạn muốn:
<loadresource property="propB">
  <propertyresource name="propA"/>
  <filterchain>
    <tokenfilter>
      <filetokenizer/>
      <replacestring from=" " to="_"/>
    </tokenfilter>
  </filterchain>
</loadresource>

Điều này sẽ thay thế tất cả "" trong propA bằng "_" và đặt kết quả trong propB. "filetokenizer" xử lý toàn bộ luồng đầu vào (thuộc tính của chúng tôi) như một mã thông báo và gắn chuỗi thay thế trên đó.

Bạn có thể thực hiện các chuyển đổi ưa thích khác bằng cách sử dụng các bộ lọc mã thông báo khác: http://ant.apache.org/manual/Types/filterchain.html


7
Cảm ơn! Nó chỉ ra bạn thậm chí có thể giảm một <filetokenizer/>chút. Mã của bạn hoạt động tốt mà không có nó (ít nhất là trên Ant v1.8.3).
Matthias

Nếu bạn đang cố gắng thực hiện việc này từ bên trong Maven, hãy xem stackoverflow.com/a/22969187/2163960
user2163960

3
Ủng hộ cho một kỹ thuật hoạt động trong vani antvà không yêu cầu thư viện bổ sung.
Christopher Schultz

57

Nếu ant-Contrib không phải là một tùy chọn, thì đây là một giải pháp di động cho Java 1.6 trở lên:

<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
Nếu metod này được sử dụng, tốt hơn hết là bạn nên đính kèm tập lệnh trong CDATA để tránh các vấn đề với phân tích cú pháp xml. <script language = "javascript"> <! [CDATA [// mã script java có thể sử dụng ký tự '<' một cách an toàn. ]]> </script>
Jan Arciuchiewicz

3
@dnault Javascript không có replaceAllchức năng cho chuỗi. Sử dụng before.replace( /\s/g, "_" )thay thế.
Trận chiến Larry

3
@LarryBattle project.getProperty()trả về a java.lang.String, vì vậy replaceAll()thích hợp trong trường hợp này. Nếu bạn muốn sử dụng replace(), bạn có thể chuyển đổi 'trước khi' vào một chuỗi Javascript mẹ đẻ với:before = new String(before);
dnault

1
project.setNewPropertysẽ dễ di động hơn, vì setPropertycó thể ghi đè giá trị thuộc tính cũ. Nó thậm chí có thể ghi vào beforetài sản.
Jarekczek

Nó yêu cầu Rhino
vintproykt

26

Trong trường hợp bạn muốn có một giải pháp mà không sử dụng Ant built-in chỉ , xem xét việc này:

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

Đầu ra là ${propB} = "This_is_a_value"


2
Ai dọn dẹp một số.tmp.file?
ngừng

Vì những người khác có thể muốn sử dụng cái này; Thêm <delete file = "some.tmp.file" /> sau </loadfile>. Câu trả lời @ceving Câu hỏi :)
terix2k11

8

Sử dụng một số ứng dụng bên ngoài như sed:

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

Nếu bạn chạy Windows, hãy tải nó lên googling cho "gnuwin32 sed".

Lệnh s/_/./gthay thế mọi _bằng . Tập lệnh này hoạt động tốt trong cửa sổ. Theo linux arg có thể cần trích dẫn.


8

Hai khả năng:

thông qua tác vụ tập lệnh và công cụ javascript nội trang (nếu sử dụng 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>

hoặc sử dụng 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>

để ghi đè thuộc tính hiện ra propA chỉ cần thay thế propB bằng propA


7

Đây là một phiên bản tổng quát hơn về câu trả lời của Uwe Schindler :

Bạn có thể sử dụng a macrodefđể tạo một tác vụ tùy chỉnh.

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

bạn có thể sử dụng điều này như sau:

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

điều này sẽ khá hữu ích nếu bạn làm điều này nhiều lần


3

Thêm một câu trả lời ví dụ hoàn chỉnh hơn câu trả lời trước đó

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

1

Chỉ là FYI cho câu trả lời Thay thế các ký tự trong thuộc tính Ant - nếu bạn đang cố gắng sử dụng điều này bên trong thực thi maven, bạn không thể tham chiếu trực tiếp các biến maven. Bạn sẽ cần một cái gì đó như thế này:

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

Những phần nào liên quan đến thay thế " "để "_"?
Jin Kwon

Ngoài ra trong maven, bạn có thể tránh được những nhu cầu bất động sản sử dụng propATemp bằng cách thay thế <propertyresource name="propATemp"/>với<string value="${propA}"/>
Ed Randall

1

Không thể thay đổi thuộc tính nhưng vars antContrib ( http://ant-contrib.sourceforge.net/tasks/tasks/variable_task.html ) thì có thể.

Đây là một macro để thực hiện tìm / thay thế trên 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>

Sau đó, gọi macro như:

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

Đoạn mã trên sử dụng javascript tách rồi nối, nhanh hơn regex. thuộc tính "cục bộ" được chuyển sang JavaScript để không bị rò rỉ thuộc tính.


0

Hoặc ... Bạn cũng có thể thử Nhiệm vụ của riêng mình

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

KẾT NỐI:

run:
     [echo] propA=This is a value
     [echo] propB=This_is_a_value
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.