2

I'm a beginner in powershell scripting, I want to be able to distinguish between the outputs of a script. Lets take as an example this script test.ps1:

param([System.String] $w)
$x=$w+" is correct"
$y=$w+ " is false"
$x
$y

to execute it and retrieve the values $x & $y, I'm doing this:

$a=.\test1.ps1 -w test
$a[0] #this is x
$a[1] # this is y

is there a way we can use something similar to $a.x to retrieve the $x value?

Thanks.

mklement0
  • 382,024
  • 64
  • 607
  • 775
user3146966
  • 165
  • 1
  • 1
  • 6

2 Answers2

4

To do what you want, you will need an object that contains a key/value pair or named properties. For example, you can create an object called a with properties x and y:

$x = "one"
$y = "two"
$a = [pscustomobject]@{"x"=$x;"y"=$y}

Testing the Above Case:

$a

x   y
-   -
one two

$a.x
one
$a.y
two

I like the link PSCustomObjects for an explanation of creating and using custom objects.

Testing with a Function:

function test {

param([string] $w)

$x = $w + "x"
$y = $w + "y"

[pscustomobject]@{"x"=$x; "y"=$y}
}

$a = test "my property "
$a

x             y
-             -
my property x my property y


$a.x
my property x
$a.y
my property y
AdminOfThings
  • 23,946
  • 4
  • 17
  • 27
0

AdminOfThings' helpful answer shows one approach to providing key-based access to values, a [pscustomobject].

In general terms, you're looking for a dictionary or hash table (hashtable): a collection of key-value pairs that allow efficient lookup of a value by its associated key.

In fact, the [pscustomobject] technique in the linked answer is syntactically based on PowerShell's hashtable literal syntax, @{ <key> = <value>; ... }[1].

Example using a script block ({ ... }) instead of a script/function for brevity:

$output = & { 
  # Output a hashtable
  @{ x = 'one'; y = 'two' } 
}

# Access the entries by key:

# Index syntax:
$output['x'] # -> 'one'
$output['y'] # -> 'two'

# Dot notation, as with objects, works too.
# While this is convenient, it is much slower with variable-based keys;
# e.g., $output.$keyName - this typically won't matter, but may in loops
# with a high number of iterations.
$output.x # -> 'one'
$output.y # -> 'two'

If the order in which entries are enumerated matters, use an ordered hashtable (PSv3+): [ordered] @{ <key> = <value>; ... }.
You only pay a negligible performance penalty for using an ordered hashtable, so I suggest using [ordered] as a matter of habit, as it makes for a nicer output and debugging experience to see the entries in the same order in which they were defined.


Choosing between a [pscustomobject] and a hashtable:

  • If you conceive of the output as a single object with the values stored in properties, use [pscustomobject], but note that constructing an object is slower than constructing a hashtable.

  • If the output is just a collection of key-value pairs, use a(n ordered) hashtable.

If performance matters (in loops with many iterations):

  • Use (ordered) hashtables.

  • Use index access with non-literal keys (e.g., $key = 'one'; $ht[$key]), which is much faster than non-literal dot notation (e.g., $key = 'one'; $ht.$key)


[1] Note, however, that [pscustomobject] @{ ... } is syntactic sugar in that a custom object is directly constructed - no intermediate hashtable is created; additionally, the properties defined by the hashtable keys are defined in definition order, whereas a hashtable guarantees no particular ordering of its entries unless you use [ordered] @{ ... }.

mklement0
  • 382,024
  • 64
  • 607
  • 775