I have the following string called MasterVersion
:
1.1-SNAPSHOT
I need to split it by the . and the - so it becomes a string[]
array called SplitVersion
, i.e.:
1
1
SNAPSHOT
I've tried everything I can think of including about a dozen variations of the below, with no joy:
<!-- doesn't work -->
<ItemGroup>
<VersionDelimiters Include="." />
<VersionDelimiters Include="-" />
<SplitVersion Include="$(MasterVersion.Split(@VersionDelimiters))" />
</ItemGroup>
<!-- doesn't work either -->
<ItemGroup>
<SplitVersion Include="$(MasterVersion.Split([`.`; `-`]))" />
</ItemGroup>
What obscure MSBuild syntax am I missing/mucking up?
To split a String with multiple characters as delimiters in C#, call Split() on the string instance and pass the delimiter characters array as argument to this method. The method returns a String array with the splits.
Split(char[], StringSplitOptions) Method This method is used to splits a string into substrings based on the characters in an array. You can specify whether the substrings include empty array elements. Syntax: public String[] Split(char[] separator, StringSplitOptions option);
MSBuild 4.0 property functions cannot handle arrays (well basically), however when you do a
Split(`,`, `-`)
You are invoking the String.Split(params string[])
overload, which requires an array (even in C# the params
keyword will create an array behind the scene and do something like Split(new string[] { ',', '-' })
internally).
What you could do is the following:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0">
<PropertyGroup>
<MasterVersion>1.1-SNAPSHOT</MasterVersion>
</PropertyGroup>
<ItemGroup>
<SplitVersion Include="$(MasterVersion.Replace(`-`, `.`).Split(`.`))" />
</ItemGroup>
<Target Name="Test">
<Message Importance="high" Text="@(SplitVersion)"/>
</Target>
</Project>
Or you could first create the (string) array to be passed to Split:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<MasterVersion>1.1-SNAPSHOT</MasterVersion>
<Delimiters>.;-</Delimiters>
<DelimitersArray>$(Delimiters.Split(`;`))</DelimitersArray>
</PropertyGroup>
<ItemGroup>
<SplitVersion Include="$(MasterVersion.Split($(DelimitersArray)))" />
</ItemGroup>
<Target Name="Test">
<Message Importance="high" Text="@(SplitVersion)"/>
</Target>
</Project>
Which is not really better in this case ;-)
Oh, and you might want to check out this MSDN blog entry for more useful information.
Update for a comment:
The "content" of SplitVersion
is technically an "array of ITaskItem", yes.
You would deal with it however you would deal with Items (of ItemGroups);
including things like "batching", etc.
You cannot really "access things by index" in msbuild project files. Expressions like
$(SplitVersion)[0]
or @(SplitVersion)[0]
or @(SplitVersion[0])
don't
do what you'd think/like. If you really would to you could assign individual
properties for "array elements" by "index".
Example:
<PropertyGroup>
<SplitVersion0>$(MasterVersion.Split($(DelimitersArray))[0])</SplitVersion0>
<SplitVersion1>$(MasterVersion.Split($(DelimitersArray))[1])</SplitVersion1>
<SplitVersion2>$(MasterVersion.Split($(DelimitersArray))[2])</SplitVersion2>
</PropertyGroup>
The array-indexing operator works here, because in this case you are still "in the context" of the .NET expression. Once that is assigned to a property (or item group) you cannot do that anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With