2016-08-04 15 views
1

ich eine Reihe von gültigen XML (mit den XML-Tags, Attribute, Kommentare, Leerzeichen, etc.), die spezielle Zeichen der Form enthält:Groovy String replaceAll nicht wie erwartet funktioniert

% (*)

zum Beispiel %(testLibDir) oder %(ivySettingsFile) usw.

ich versuche, alle Instanzen von %(*) mit ${*} zu ersetzen. So zum Beispiel, wenn %(testLibDir) existiert in meinem XML-String (unabhängig davon, wie viele Vorkommen), dann will ich es in ${testLibDir} umgewandelt usw.

Mein bester Versuch so weit:

static void main(String[] args) { 
    // In reality the XML string will be generated dynamically at runtime. 
    String xml = """ 
    <project name="some-name" default="dist" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant"> 

    <!-- specify properties in build.properties --> 
    <property file="build.properties" /> 

    <taskdef name="ivy-configure" classname="org.apache.ivy.ant.IvyConfigure" /> 
    <taskdef name="ivy-resolve" classname="org.apache.ivy.ant.IvyResolve" /> 
    <taskdef name="ivy-retrieve" classname="org.apache.ivy.ant.IvyRetrieve" /> 
    <taskdef name="ivy-cleancache" classname="org.apache.ivy.ant.IvyCleanCache" /> 

    <!-- Identify the Ivy settings file to use --> 
    <ivy:settings file="%(ivySettingsFile)" /> 

    <target name="test-resolve"> 
    <delete> 
     <fileset dir="%(testLibDir)" includes="*.jar" /> 
    </delete> 
    <ivy:resolve file="test-ivy.xml" conf="compile" /> 
    <ivy:retrieve pattern="%(testLibDir)/[artifact]-[type]-[revision].[ext]" conf="compile" /> 
    </target> 
    """ 
    println "Final XML is:\n${xml.replaceAll('%(', '\${').replaceAll(')', '}')}" 
} 

Die println oben erzeugt die folgende Stacktrace:

log4j:ERROR Could not find value for key log4j.appender.stdout.layout 
log4j:WARN No such property [file] in org.apache.log4j.ConsoleAppender. 
Exception in thread "main" java.util.regex.PatternSyntaxException: Unclosed group near index 2 
%(
^ 
    at java.util.regex.Pattern.error(Pattern.java:1955) 
    at java.util.regex.Pattern.accept(Pattern.java:1813) 
    at java.util.regex.Pattern.group0(Pattern.java:2908) 
    (rest of stack trace omitted for brevity) 

Irgendwelche Ideen, wo ich schief gehe und was ich tun kann meinen String Ersatz zu beheben?

Antwort

2

Sie benötigen einen regulären Ausdruck zu verwenden, wie:

/%\(([^()]*)\)/ 

  • % übereinstimmen - ein Prozentsatz singen
  • \( - eine wörtliche (
  • ([^()]*) - Gruppe 1 Capturing 0+ andere Zeichen als ( und )
  • \) - eine wörtliche )

Beachten Sie, dass sich das Muster besser mit Slashy Strings definiert ist, und die wörtliche $ im Ersetzungsmuster sollte als wörtliche Dollar-Symbol mit einer wörtlichen \ behandelt werden entwertet werden . $1 ist ein Rückreferenzierung des von Gruppe erfasste Wert 1.

Groovy demo:

println xml.replaceAll(/%\(([^()]*)\)/, '\\${$1}')