Friday, February 23, 2018

PowerShell’s $OFS built-in Variable And What It Does

The other day, I was working on converting some C'# to PowerShell. 95% was trivial and almost muscle memory. Then I came to this block of C#

char[] chars = { 'w', 'o', 'r', 'd' };
string string1 = new string(chars);
Console.WriteLine(string1);

The output is:

word

So I initially translated it as:

[char[]] $Chars =  ('w', 'o', 'r', 'd' )
[String $String1 = $Chars
Write-Host $String1

But that produced:

w o r d

The same characters but with spaces between which seemed illogical (at first!). I scratched my head, and did a bit of digging over at Spiceworks, where I was introduced to the $OFS PowerShell Variable. $OFS holds a string, known as the Output Field Separator.   PowerShell uses this character string to separate array elements when it coverts the array to the string, PowerShell has a default value of  ” ”, but you can change at the command line, in a script, or in your Profile. The issue here is that PowerShell is doing the array to string conversion and separates each character in the char array with the separator (“ “). You can read a bit more about this in an old blog post by Jeffrey Snover:

This gave rise to two solutions. The first is to let .NET do the conversion and the second was to leverage $OFS. Here  are two ways to do it: https://blogs.msdn.microsoft.com/powershell/2006/07/15/psmdtagfaq-what-is-ofs/


# Leveraging $OFS
[char[]] $Chars =  ('w', 'o', 'r', 'd' )
$OFS = ''  # Set separator to null
[String] $String1 = $Chars
Write-Host $String1
# Or using .NET directly
[char[]] $chars =  ('w', 'o', 'r', 'd' )
$String2 = [System.String]::New($Chars)
Write-Host $string2

This is interesting, but there is a highly practical solution to an issue I’ve seen brought up in several PowerShell support places. The issue if how to construct a comma separated string of words. So if you had an array of several words such as (‘X423q420’, ‘JG75-01-27’,”PCNY”) you could easily concatenate them as follows:

$Array = (‘X423q420’, ‘JG75-01-27’,”PCNY”)
[string] $Array

Which produces:


X423q420,JG75-01-27,PCNY

You could also create the array from properties then force it to be separated by $OFS, like so:

$F = Get-ChildItem –Path X.XML
$OFS = ','
$Sring3 = [string] ($F.Fullname, ($f.length/1kb).ToString('n3'))
Write-Host $String3

Which produces this:

C:\foo\X.XML,0.317

You learn something nearly every day!




No comments: