1

I am trying to concatenate a variable with a string but get always a space a inbetween

[xml] $buildConfig = Get-Content $paths_target_file_path
$ver = $buildConfig.Project.PropertyGroup.LibVersion
$ver = $ver -replace "\s+",""
$version = "V"+$ver
Write-Host "Downloading LIB version: $version"

The above output is Downloading Lib version: V 1.2.11 i.e. a space between V and 1.2.11 despite replacing any whitespace character

Markus

Huaraz
  • 11
  • 1
  • 1
    are you certain that the apparent space is actually a standard space? there are other chars that look like a space. one way to test would be to feed `$Ver` to `Format-Hex` and see what the actual char codes are. – Lee_Dailey Jul 24 '21 at 20:03
  • 1
    @Lee_Dailey: `\s` also covers Unicode variations of the ASCII space char. (e.g., ([`U+00A0`](http://www.fileformat.info/info/unicode/char/a0), the no-break space) - do you know of any character that _presents_ like a space yet isn't matched by `\s`? `Format-Hex` isn't an option in Windows PowerShell, because it represents any non-ASCII chars. as `3f`== literal `?`. In PowerShell Core it shows _the bytes that make up the UTF-8 encoding_ of non-ASCII characters, which can be confusing. There is no straightforward built-in solution; see [this answer](https://stackoverflow.com/a/68328388/45375). – mklement0 Jul 24 '21 at 20:25
  • 3
    I bet `$ver` is not of the type string. – Santiago Squarzon Jul 24 '21 at 21:41
  • Unfortunately I can't reproduce it anymore after changing my xml file :-( . I 'll come back if it reappears. Thank you – Huaraz Jul 26 '21 at 17:13

1 Answers1

3

The implication is that $ver contains an array of strings, not just a single string:

  • The -replace operator can operate on arrays as the LHS, in which case the operation is applied to each element of the array, and the results are again returned as an array.

  • When PowerShell stringifies an array - such as when using explicit string concatenation with + or in implicitly inside an expandable string ("...") - it joins the array elements with a space between them.

Therefore, your symptom implies that $ver is not a single string, but a 2-element array whose first element is the empty string:

A simple demonstration:

$ver = ('', ' foo ') -replace '\s+'

'V' + $ver

The above yields verbatim V foo

To use the first non-empty element of the $ver array, use the following:

'V' + ($ver -ne '')[0]  # -> 'Vfoo'
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Right, I think If OP tries `[string]$ver = $buildConfig.Project.PropertyGroup.LibVersion` he would see the expected result. Similar to `$ver = [string]('', ' foo ') -replace '\s+'` from your example. Excellent answer. – Santiago Squarzon Jul 25 '21 at 00:18
  • 1
    Thanks, @SantiagoSquarzon, but your command wouldn't prevent the space. Try `[string] $ver = '', 'foo'; "[$ver]"` – mklement0 Jul 25 '21 at 00:28
  • Right, I mean something like `[string]($buildConfig.Project.PropertyGroup.LibVersion) -replace '\s+'` from OP's question. I think that should work, its hard to tell tho without inspecting the object. – Santiago Squarzon Jul 25 '21 at 00:52
  • @SantiagoSquarzon, if the LHS of the `-replace` operation is an array, so is the return value, so the `-replace` makes no difference. – mklement0 Jul 25 '21 at 01:31
  • 1
    I understand what you mean but `$ver = [string]('', ' foo ') -replace '\s+'` gives me the expected results which is why I assume that from OP's question `$ver = [string]($buildConfig.Project.PropertyGroup.LibVersion) -replace '\s+'` should also give the expected result. – Santiago Squarzon Jul 25 '21 at 01:59
  • That's because the `[string]` cast has higher precedence than the `-replace` operation - see the conceptual [about_Operator_Precedence](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Operator_Precedence) help topic. The real test is (note the extra parentheses): `$ver = [string] (('', ' foo ') -replace '\s+'); "[$ver]"` – mklement0 Jul 25 '21 at 02:06
  • @SantiagoSquarzon, I see what you're saying now. Yes, if you force the LHS array to a space-separated string first and then _remove all spaces_, you'll get the desired result too, but, for conceptual clarity, I suggest isolating the single array element of interest first. – mklement0 Jul 25 '21 at 02:12
  • 1
    @SantiagoSquarzon, but, to be clear: the version with the _type constraint_, from your _first_ comment, would _not_ work, because the `[string]` cast is then applied _after_ the `-replace` operation (to recap: `[string] $ver = ('', 'foo') -replace '\s+'; "[$ver]"`) – mklement0 Jul 25 '21 at 02:17
  • 1
    Yeah you're totally right, from my first comment, the first example would not work I realized that later after trying. – Santiago Squarzon Jul 25 '21 at 02:49