0

These things drive me nuts:

enter image description here

Is there an easy way to have Powershell just show me the empty string and the list with an empty string in it?

Kristoffer
  • 63
  • 1
  • 1
  • 4

3 Answers3

4

For a while I am maintaining a ConvertTo-Expression which converts an (complex) object into a PowerShell expression which eventually can be used to rebuild most objects. It might useful in situations as comparing test results but also to reveal objects. For details see: readme.

Source and installation

The ConvertTo-Expression script can be installed from the PowerShell Gallery:

Install-Script -Name ConvertTo-Expression

As it concerns a standalone script, installation isn't really required. If you don't have administrator rights, you might just download the script (or copy it) to the required location. You might than simply invoke the script using PowerShell dot sourcing:

. .\ConvertTo-Expression.ps1

Example

The following command outputs the same expression as used to build the object:

$Object = [Ordered]@{
    'Null' = $Null
    'EmptyString' = ''
    'EmptyArray' = @()
    'SingleItem' = ,''
    'EmptyHashtable' = @{}
}
ConvertTo-Expression $Object

Note the comment from @Mathias there's no functional difference between "one string" and "an array of one string", the pipeline consumes 1 string either way. PowerShell is not node which is described here: PowerShell enumerate an array that contains only one inner array. Some objects might be really different than you expect.

See also: Save hash table in PowerShell object notation (PSON)

iRon
  • 20,463
  • 10
  • 53
  • 79
1

This is PowerShell, not Node. So it's not JavaScript or JSON. Also, PowerShell is not Bash or CMD any other regular text-based shell. PowerShell works with objects. .NET objects, in particular. And how objects are represented as text is ... quite a matter of taste. How to represent null? Of course: nothing. How to represent an empty string? Nothing, either. An empty array ... you get my point.

All pipeline output is by default send to Out-Default. In general, the way objects are represented can be controlled by format files: about_Format.ps1xml and about_Types.ps1xml. From PowerShell 6 upwards, the default formats are compiled into the source code, but you can extend them. How you do so, depends on your personal taste. Some options were already mentioned ConvertTo-Json "", ConvertTo-Json @("")), but this would be veryyy JSON-specific.

tl;dr Don't care too much about how objects are represented textually. As you see, there are many possible ways to do so, and also some others. Just make sure your scripts are always object-oriented.

marsze
  • 15,079
  • 5
  • 45
  • 61
0

You mean like Python's repr() function? A serialization? "Give me a canonical representation of the object that, when property evaluated, will return an object of the type originally passed?" No, that's not possible unless you write it yourself or you serialize it to XML, JSON, or similar. That's what the *-CliXml and ConvertTo-*/ConvertFrom-* commands are for.

On Powershell 7:

PS C:\> ''.Split(',') | ConvertTo-Json -Compress -AsArray
[""]
PS C:\> '1,2,3,,5'.Split(',') | ConvertTo-Json -Compress -AsArray
["1","2","3","","5"]

The closest would be the ToString() common method. However, that's intended for formatting output and typecasting, not canonical representations or serializations. Not every object even has a string representation that can be converted back into that object. The language isn't designed with that in mind. It's based on C#, a compiled language that favors binary serializations. Javascript requires essentially everything to have a string serialization in order to fulfill it's original design. Python, too, has string representations as fundamental to it's design which is why the repr() function is foundational for serialization and introspection and so on.

C# and .Net go the other way. In a .Net application, if you want to specify a literal empty string you're encouraged to use String.Empty ([String]::Empty in Powershell) because it's easier to see that it's explicit. Why would you ever want a compiled application to tell the user how the canonical representation of an object in memory? You see why that's not a useful thing for C# even if it might be for Powershell?

Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
  • 1
    Good pointers, but by using `-AsArray` you're artificially turning any input into an array, even if it isn't. As shown by Mathias in the comments, pass the expression as an _argument_: `ConvertTo-Json -Compress (''.Split(','))` - that also makes it work in earlier versions. – mklement0 Oct 17 '20 at 14:26
  • @mklement0 That was intentional. His code example code was trying to turn it into an array. It's not clear to me what he's intending the `@()` to do, so I'm assuming he wants it as an array. – Bacon Bits Oct 18 '20 at 19:21
  • I think the OP has the misconception that `''.split(',')` returns the empty string as a _single string_, whereas in reality it is the same as `'@('.split(','))` (almost, given that the former returns `[string[]]` and the latter `[object[]]`). A way of diagnostically printing the values of these expressions _as-is_ would have cleared up that particular misconception and is also generally helpful to distinguish scalars from arrays. – mklement0 Oct 18 '20 at 19:45
  • @mklement0 That's possible but I don't think it's really a useful distinction. I don't think it's clarity that OP must have to understand my answer. Firstly, I think if you're going to be working with `String.Split()` you're going to be writing code that handles with arrays, and, secondly, Powershell largely handles scalar and arrays identically. I think the consistency is more important. If you still don't agree and want to argue minutae of single element arrays versus scalars, you're welcome to add your own answer. I don't think it's relevant. – Bacon Bits Oct 18 '20 at 20:48
  • I'm saying your answer doesn't fulfill the requirement "show the actual value", as requested in the question's title, and as fulfilled by the accepted answer: the ability to precisely represent the actual value in a diagnostic form that allows you to tell whether it's a scalar, or an array, or a nested array, ... is what this question is about (as hinted at by the start of your answer) and what makes it interesting to future readers. Happy to leave it at that (and no need for another answer - the accepted one has it covered). – mklement0 Oct 18 '20 at 21:00