How to transform property into multiple arguments to <exec> task

瘦欲@ 提交于 2019-12-22 18:01:57

问题


I have a property that contains multiple values, and I want to execute a command with a separate "-j" argument for each value in the property.

E.g. <property name="arguments" value="foo bar hello world"/>

Should execute: mycommand -j foo -j bar -j hello -j world

I'm using Ant 1.7.1, so I can't use the "prefix" attribute (Ant 1.8) on the <arg> element of an <exec> task.

One workaround is to insert the "-j" directly into the property by hand and then use the "line" attribute of <arg>:

<property name="args" value="-j foo -j bar -j hello -j world"/>
<exec executable="mycommand">
    <arg line="${args}"/>
</exec>

...But I prefer to have the property be a simple list without the embedded arguments.

Edit: Actually, my arguments are paths within an XML file, so a more accurate argument list would be:

<property name="arguments" value="/foo/bar /hello/world /a/very/long/path"/>

I would like the command to then execute with arguments: "-j /foo/bar -j /hello/world -j /a/very/long/path". Note that the slashes remain forward slashes even under Windows (these are arguments to a command, not filenames).


回答1:


You can use Ant resource tools for this.

<property name="arg_list" value="foo bar hello world"/>    
<resources id="arguments">
  <mappedresources>
    <string value="${arg_list}" />
    <filtermapper>
      <replacestring from=" " to=" -j "/>
    </filtermapper>
  </mappedresources>
</resources>
<property name="arguments" value="-j ${toString:arguments}" />

The above will result in property arguments having the value -j foo -j bar -j hello -j world, which can then be used in the exec arg line.

Alternatively a pathconvert task can help in this regard:

<property name="arg_list" value="foo bar hello world"/>    
<pathconvert property="arguments" pathsep=" ">
  <chainedmapper>
    <flattenmapper />
    <regexpmapper from="(.*)" to="-j \1" />
  </chainedmapper>
  <filelist files="${arg_list}" />
</pathconvert>

If you have absolute paths, rather than just strings in the list, then remove the flattenmapper.

If you have relative paths, replace the flattenmapper line with:

<globmapper from="${basedir}/*" to="*" />

to prevent the paths being converted to absolute.

In the event that you have UNIX-like paths in the arg_list on a Windows system the default settings for pathconvert won't work - the paths get converted to Windows style. Instead, to process the list use:

<pathconvert property="arguments" pathsep=" " targetos="unix">
  <chainedmapper>
    <regexpmapper from="C:(.*)" to="-j \1" />
  </chainedmapper>
  <filelist files="${arg_list}" />
</pathconvert>

Note the targetos setting and the revised regexmapper from argument.




回答2:


Use some for loop, here's a solution based on Ant Addon Flaka :

<project name="demo" xmlns:fl="antlib:it.haefelinger.flaka">

 <!-- make standard ant tasks like i.e. exec understand EL expressions -->
 <fl:install-property-handler/>

 <property name="arguments" value="foo bar hello world"/>

 <fl:for var="arg" in="split('${arguments}',' ')">
  <exec executable="mycommand">
   <arg line="#{arg} -j"/>
  </exec>
 </fl:for>

</project>



回答3:


Not sure your comfort with scripting languages, but you can also embed script to do the parsing/reassembling:

http://ant.apache.org/manual/Tasks/script.html

I will say, I think it's a bit fragile because you have an explicit reference to the ANT project's name, but up to you:

<?xml version="1.0" encoding="utf-8"?>
<project name="ScriptProj" basedir=".">

    <property name="arguments" value="foo bar hello world"/>

    <target name="test">

        <script language="javascript">
            <![CDATA[

                argsParm = ScriptProj.getProperty("arguments");
                argsParmAmend = "";
                args = argsParm.split(" ");

                for (i = 0; i < args.length; i++)
                    argsParmAmend = argsParmAmend + "-j " + args[i] + " ";

                // remove trailing string
                ScriptProj.setProperty("arguments.amended", argsParmAmend.substr(0, argsParmAmend.length-1));
            ]]>
        </script>

        <echo>${arguments}</echo>
        <echo>${arguments.amended}</echo>

    </target>

</project>


来源:https://stackoverflow.com/questions/9100579/how-to-transform-property-into-multiple-arguments-to-exec-task

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!