2009-07-24 25 views
81

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ó vào một thuộc tính khác với các ký tự nhất định được thay thế?Thay thế các ký tự trong thuộc tính Ant

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

Trả lời

86

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

Tôi nghĩ rằng bạn muốn:

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

Đáng tiếc là các ví dụ đưa ra là không terribly rõ ràng, nhưng nó có giá trị cố gắng đó. Bạn cũng nên kiểm tra xem điều gì sẽ xảy ra nếu không có dấu gạch dưới nào - bạn có thể cần sử dụng tùy chọn defaultValue.

+1

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: nếu không, nếu không có kết quả phù hợp, không có gì được đưa vào propB !! Cảm ơn! –

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 nhận được nó googling cho "GnuWin32 sed".

Lệnh s/_/./g thay thế mỗi _ bằng . Tập lệnh này chạy tốt dưới cửa sổ. Dưới linux arg có thể cần trích dẫn.

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> 

Output được ${propB} = "This_is_a_value"

+2

Ai dọn some.tmp.file? – ceving

+0

Vì những người khác có thể muốn sử dụng điều này; Thêm sau. Câu trả lời @ceving Câu hỏi :) – terix2k11

51

Nếu ant-contrib không phải là một lựa chọn, đây là một giải pháp di động cho Java 1.6 và sau này:

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

Nếu metod này được sử dụng nó sẽ là tốt để kèm theo kịch bản trong CDATA để tránh các vấn đề với xml phân tích cú pháp.

+3

@dnault Javascript không có một 'chức năng replaceAll' cho chuỗi. Sử dụng 'before.replace (/ \ s/g," _ ")' để thay thế. –

+3

@LarryBattle 'project.getProperty()' trả về một 'java.lang.String', vì vậy' replaceAll() 'là 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 'before' thành một chuỗi JavaScript gốc với: 'before = new String (trước);' – dnault

8

Có hai khả năng:

qua nhiệm vụ kịch bản và động cơ javascript BUILTIN (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 đè lên exisiting tài sản propA chỉ đơn giản là thay thế propB với propA

84

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

Bí quyết là sử dụng các nguồn lực ANT của:

  • Có một loại tài nguyên được gọi là "propertyresource" mà giống như một file nguồn, nhưng cung cấp một dòng từ chuỗi giá trị của khu vực 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ư "copy" chấp nhận các tệp
  • Ngoài ra còn có nhiệm vụ "loadresource" có thể tải bất kỳ tài nguyên nào đến một thuộc tính (ví dụ: tệp), nhưng điều này cũng có thể tải tài sản của chúng tôi. Nhiệm vụ này cho phép lọc đầu vào bằng cách áp dụng một số biến đổi mã thông báo.Cuối cùng sau đây 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> 

một 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) dưới dạng một mã thông báo và áp dụng chuỗi thay thế trên đó.

Bạn có thể làm biến đổi lạ mắt khác sử dụng tokenfilters khác: http://ant.apache.org/manual/Types/filterchain.html

+4

Cảm ơn! Hóa ra bạn thậm chí có thể thả bit ''. 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

+0

Nếu bạn đang cố thực hiện điều này từ bên trong Maven, hãy xem http://stackoverflow.com/a/22969187/2163960 – user2163960

+1

Upvote cho một kỹ thuật hoạt động trong vanilla 'ant' và không yêu cầu thư viện bổ sung. –

1

Chỉ cần một FYI cho câu trả lời Replacing characters in Ant property - nếu bạn đang cố gắng sử dụng bên này của một thi maven, bạn không thể tham khảo các biến maven trực tiếp. 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" /> 
... 
+0

Những phần nào liên quan đến việc thay thế '" "' thành '" _ "'? –

+0

Hoặc trong maven, bạn có thể tránh sự cần thiết phải sử dụng thuộc tính 'propATemp' bằng cách thay thế' 'bằng' ' –

4

Dưới đây là một phiên bản tổng quát hơn của Uwe Schindler's answer:

Bạn có thể sử dụng một macrodef để tạo ra một nhiệm 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="_"/> 

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

0

Hoặc ... Bạn cũng có thể thử Your Own Task

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> 

CONSOLE:

run: 
    [echo] propA=This is a value 
    [echo] propB=This_is_a_value 
2

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

<property name="propB_" value="${propA}"/> 
<loadresource property="propB"> 
    <propertyresource name="propB_" /> 
    <filterchain> 
    <tokenfilter> 
     <replaceregex pattern="\." replace="/" flags="g"/> 
    </tokenfilter> 
    </filterchain> 
</loadresource> 
Các vấn đề liên quan