3

This answer includes a Powershell like of code that splits $env:path, applies a filter and puts the result together, to store it in $env:path.

$path = ($path.Split(';') | Where-Object { $_ -ne 'ValueToRemove' }) -join ';'

I was reading this code, and then, suddenly, a wild -join ';' appears. How does this work? What is the concept behind this? I would expect (<expression) would eventually become some object, but then this like reads <object> -join ';', so the join part would still be some independent token. How is it evaluated? I can see that it obviously does "the right thing", but how and why does it work? How exactly does Powershell evaluate this line? Looks like very dark magic to me.

Clijsters
  • 4,031
  • 1
  • 27
  • 37
user1129682
  • 989
  • 8
  • 27

2 Answers2

4

As stated out by the docs the -Join Operator can be used mainly in two ways:

-Join <String[]>
<String[]> -Join <Delimiter>

Most of PowerShells operators work this way (and look similiar to method parameters). You got some values on the left side of an operator and execute an action (in this case joining) with the right-side-token, in your case the semicolon ;.

Take a look at the help (by typing Get-Help <section_name>) sections about_Join and about_Operators

Also a nice example copied from the docs (without the need of splitting beforehand) is:

PS> $a = "WIND", "S P", "ERSHELL"
PS> $a -join "OW"
WINDOWS POWERSHELL
Clijsters
  • 4,031
  • 1
  • 27
  • 37
  • 1
    Oh, so `-join`, which looks like a parameter to a command, is an operator, just like `-` is an operator, which is a substring of `-join`. I see. That pointer to the list of operators PS knows was most helpful. – user1129682 Feb 06 '18 at 10:24
  • Yes, exactly. Additional ones are `-split` (which your example could have used, instead of `$path.split`), `-and`, `-as`, `-replace` and many more. – Clijsters Feb 06 '18 at 11:04
1

To add to Clijsters' answer, it's an operator that acts on a string array (String[]). The character following the operator specifies the character to use to join each element of the array.

To break down the parts:

($path.Split(';')                        # take the *string* $path and split into an *array*.
                                         # do this on the ; character

Where-Object { $_ -ne 'ValueToRemove' }) # exclude the array element which is equal to
                                         # "ValueToRemove" 

-join ';'                                # Join the *array* back into a *string*
                                         # Put ";" between each array element.
G42
  • 9,791
  • 2
  • 19
  • 34
  • I see. So the `()` evaluates to an array, which supports the `-join` operator. Guess that was just too much at once for me to grasp. – user1129682 Feb 06 '18 at 10:26
  • @user1129682 Exactly. It evaluates to an array because the `.Split()` method is used to break up the string. [This scripting guy post](https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/17/using-the-split-method-in-powershell/) goes into more detail on the `Split()` method. – G42 Feb 06 '18 at 10:56
  • I thought, the part where the array is created and filtered was clear to the OP. thanks for that addition! – Clijsters Feb 06 '18 at 11:01
  • @Clijsters: not really. I expect split to generate some form of iterable, but I had no idea what the result of piping the array though `Where-Object` would be. – user1129682 Feb 06 '18 at 11:25