Convert array output to table using PowerShell - powershell

I'm exporting certificates from Windows CA which is an array which has data in below format. I want to convert into table. Any idea?
From:
$a=#(
'a=all
b=call
',
'a=all
b=ll'
)
Current output:
a=all
b=call
a=all
b=ll
Desired output:
a b
all call
all ll

What you have is an array of multiline strings. For the desired output you need an array of objects:
$a = #(
[PSCustomObject]#{
'a' = 'all'
'b' = 'call'
},
[PSCustomObject]#{
'a' = 'all'
'b' = 'll'
}
)
If your input data is actually a list of multiline strings with lines of the form key=value you can transform those into custom objects like this:
$a = #(
'a=all
b=call',
'a=all
b=ll'
)
$a | ForEach-Object {
[PSCustomObject]($_ | ConvertFrom-StringData)
}
ConvertFrom-StringData converts a string with one or more lines of key=value pairs into a hashtable, which can then be cast into a custom object.

You can also Create an empty Array and then just add values using [PsCustomObject]
$Table = #()
$Table += [Pscustomobject]#{a = "all"; b = "call"}
$Table += [Pscustomobject]#{a = "all"; b = "ll"}

Related

PowerShell-How to get values from this JSON file

This is the partial data after removed the confidential information.
{
"WebhookName":"Azure-CustomAlert-Webhook",
"RequestBody":"{\"schemaId\":\"azureMonitorCommonAlertSchema\",\"data\":{\"essentials\":{\"alertId\":\"/subscriptions/XXXXXXXXX/providers/Microsoft.AlertsManagement/alerts/XXXXXXX\",\"alertRule\":\"Low Memory\",\"severity\":\"Sev3\",\"signalType\":\"Log\",\"monitorCondition\":\"Fired\",\"monitoringService\":\"Log Analytics\",\"alertTargetIDs\":[\"/subscriptions/XXXXX/resourcegroups/XXXX-RG/providers/microsoft.operationalinsights/workspaces/workspacename\"],\"configurationItems\":[\"USE2V5TMP9001\"],\"originAlertId\":\"XXXXX\",\"firedDateTime\":\"2022-03-09T17:49:41.4631455Z\",\"description\":\"Triggers an alert for a low memory condition\",\"essentialsVersion\":\"1.0\",\"alertContextVersion\":\"1.1\"},\"alertContext\":{\"SearchQuery\":\"Perf | where ( CounterName == \\\"% Used Memory\\\" or CounterName == \\\"% Committed Bytes In Use\\\" ) | where Computer contains (\\\"TMP\\\") | summarize AggregatedValue = avg(CounterValue) by Computer, bin(TimeGenerated, 5m)\",\"SearchIntervalStartTimeUtc\":\"2022-03-09T17:42:10Z\",\"SearchIntervalEndtimeUtc\":\"2022-03-09T17:47:10Z\",\"ResultCount\":1,\"SeverityDescription\":\"Informational\",\"WorkspaceId\":\"XXXXX\",\"SearchIntervalDurationMin\":\"5\",\"AffectedConfigurationItems\":[\"USE2V5TMP9001\"],\"AlertType\":\"Metric measurement\",\"IncludeSearchResults\":true,\"Dimensions\":[{\"Name\":\"Computer\",\"Value\":\"USE2V5TMP9001\"}],\"SearchIntervalInMinutes\":\"5\",\"SearchResults\":{\"tables\":[{\"name\":\"PrimaryResult\",\"columns\":[{\"name\":\"Computer\",\"type\":\"string\"},{\"name\":\"TimeGenerated\",\"type\":\"datetime\"},{\"name\":\"AggregatedValue\",\"type\":\"real\"}],\"rows\":[[\"USE2V5TMP9001\",\"2022-03-09T17:42:10Z\",38.267662048339851]]}],\"dataSources\":[{\"resourceId\":\"/subscriptions/XXXXX/resourcegroups/XXXX/providers/microsoft.operationalinsights/workspaces/XXXX\",\"region\":\"eastus2\",\"tables\":[\"Perf\"]}]},\"Threshold\":9,\"Operator\":\"Greater Than\",\"IncludedSearchResults\":\"True\"},\"customProperties\":null}}",
"RequestHeader":{
"Connection":"Keep-Alive",
"Expect":"100-continue",
"Host":"xxxx.webhook.eus2.azure-automation.net",
"User-Agent":"IcMBroadcaster/1.0",
"X-CorrelationContext":"RkkKACgAAAACAAAAEADvqM+sXFG+SYkp7Tcy2IZaAQAQAMflO8/GhoFLrHCgd8ILz2o=",
"x-ms-request-id":"8fdd10d2-4a36-43a5-8e65-4eb20f3b9865"
}
}
The above json i got it from the Azure Log Search alert and trying to customize it.
From the above json can i get the values if i refer the column section keys?.
Ex: If i mention computer then i should be able to get value USE2V5TMP9001 and AggregatedValue is 38.267662048339851.
Use the columns array to map the individual row values to the correct type and property name:
$json = #'
<json goes here>
'#
$data = $json |ConvertFrom-Json
$columnDefinitions = $data.columns
$rows = foreach($row in $data.rows){
# prepare dictionary to hold the individual column values
$properties = [ordered]#{}
for($i = 0; $i -lt $row.Length; $i++){
# extract value and column metadata
$value = $row[$i]
$name = $columnDefinitions[$i].name
$type = $columnDefinitions[$i].type
# make sure to translate any type names if necessary
# eg. translate `real` -> `decimal`
if($type -eq 'real'){ $type = 'decimal' }
# convert value to correct type and store in property dictionary
$properties[$name] = $value -as $type
}
# create new object based on the row values
[pscustomobject]$properties
}
$rows will now contain 1 or more objects with the expected values so you can now do:
$rows |ForEach-Object {
# this now resolves `USE2V5TMP9001`
$_.computer
}

What is '#{}' meaning in PowerShell

I have line of scripts for review here, I noticed variable declaration with a value:
function readConfig {
Param([string]$fileName)
$config = #{}
Get-Content $fileName | Where-Object {
$_ -like '*=*'
} | ForEach-Object {
$key, $value = $_ -split '\s*=\s*', 2
$config[$key] = $value
}
return $config
}
I wonder what #{} means in $config = #{}?
#{} in PowerShell defines a hashtable, a data structure for mapping unique keys to values (in other languages this data structure is called "dictionary" or "associative array").
#{} on its own defines an empty hashtable, that can then be filled with values, e.g. like this:
$h = #{}
$h['a'] = 'foo'
$h['b'] = 'bar'
Hashtables can also be defined with their content already present:
$h = #{
'a' = 'foo'
'b' = 'bar'
}
Note, however, that when you see similar notation in PowerShell output, e.g. like this:
abc: 23
def: #{"a"="foo";"b"="bar"}
that is usually not a hashtable, but the string representation of a custom object.
The meaning of the #{}
can be seen in diffrent ways.
If the #{} is empty, an empty hash table is defined.
But if there is something between the curly brackets it can be used in a contex of an splatting operation.
Hash Table
Splatting
I think there is no need in explaining what an hash table is.
Splatting is a method of passing a collection of parameter values to a command as unit.
$prints = #{
Name = "John Doe"
Age = 18
Haircolor = "Red"
}
Write-Host #prints
Hope it helps! BR
Edit:
Regarding the updated code from the questioner the answer is
It defines an empty hash table.
Be aware that Get-Content has its own parameters!
THE MOST IMPORTANT 1:
[-Raw]

Array of hash tables not output

This is a basic question but I'm stuck. I have the below code:
$array = #(
$hashtable1 = #{
Name = "Test1"
Path = "C:\Test1"
}
$hashtable2 = #{
Name = "Test1"
Path = "C:\Test1"
}
)
The array is created but empty. I have tried comma separation:
$hashtable1 = #{}, $hashtable2 = #{}
But this did not work. What is wrong?
You are assigning the hashtables as variables. Take out the variable assignment:
$array = #(
#{
Name = "Test1"
Path = "C:\Test1"
},
#{
Name = "Test1"
Path = "C:\Test1"
}
)
gms0ulman's helpful answer provides an effective solution for constructing your array of hashtables.
To provide some background information:
A variable assignment such as $hashtable1 = ... is not an expression, so it produces no output, which is why your $array = assignment ended up containing an empty array, given that #(...) saw no output.
However, you can make assignment statements produce output simply by enclosing them in (...), which turns them into expressions, which allows you to assign to the variable and output the assigned value.
#(...) is not needed to construct arrays; instead, you can use ,, the array-construction operator.
Even though it may not be needed, the following demonstrates how to both construct the array of hashtables and save the individual hashtables in dedicated variables:
$array =
($hashtable1 = #{
Name = "Test1"
Path = "C:\Test1"
}),
($hashtable2 = #{
Name = "Test1"
Path = "C:\Test1"
})

Powershell array of arrays [duplicate]

This question already has answers here:
Powershell create array of arrays
(3 answers)
Closed 5 years ago.
This is building $ret into a long 1 dimensional array rather than an array of arrays. I need it to be an array that is populated with $subret objects. Thanks.
$ret = #()
foreach ($item in $items){
$subret = #()
$subRet = $item.Name , $item.Value
$ret += $subret
}
there might be other ways but arraylist normally works for me, in this case I would do:
$ret = New-Object System.Collections.ArrayList
and then
$ret.add($subret)
The suspected preexisting duplicate question is indeed a duplicate:
Given that + with an array as the LHS concatenates arrays, you must nest the RHS with the unary form of , (the array-construction operator) if it is an array that should be added as a single element:
# Sample input
$items = [pscustomobject] #{ Name = 'n1'; Value = 'v1'},
[pscustomobject] #{ Name = 'n2'; Value = 'v2'}
$ret = #() # create an empty *array*
foreach ($item in $items) {
$subret = $item.Name, $item.Value # use of "," implicitly creates an array
$ret += , $subret # unary "," creates a 1-item array
}
# Show result
$ret.Count; '---'; $ret[0]; '---'; $ret[1]
This yields:
2
---
n1
v1
---
n2
v2
The reason the use of [System.Collections.ArrayList] with its .Add() method worked too - a method that is generally preferable when building large arrays - is that .Add() only accepts a single object as the item to add, irrespective of whether that object is a scalar or an array:
# Sample input
$items = [pscustomobject] #{ Name = 'n1'; Value = 'v1'},
[pscustomobject] #{ Name = 'n2'; Value = 'v2'}
$ret = New-Object System.Collections.ArrayList # create an *array list*
foreach ($item in $items) {
$subret = $item.Name, $item.Value
# .Add() appends whatever object you pass it - even an array - as a *single* element.
# Note the need for $null = to suppress output of .Add()'s return value.
$null = $ret.Add($subret)
}
# Produce sample output
$ret.Count; '---'; $ret[0]; '---'; $ret[1]
The output is the same as above.
Edit
It is more convoluted to create an array of tuples than fill an array with PsObjects containing Name Value as the two properties.
Select the properties you want from $item then add them to the array
$item = $item | select Name, Value
$arr = #()
$arr += $item
You can reference the values in this array by doing this
foreach($obj in $arr)
{
$name = $obj.Name
$value = $obj.Value
# Do actions with the values
}

get first two digits by using split method in powershell

I want to split one output. the output is
02|05|002|004|0014|0035|R
I tried with
$state.ToString().Split("|")[0]
i got the result like System.Object[]
i want to split the output and assigning to variables like
$a='02'
$b='05'
please help me to complete this
Here's a simplified solution that uses the range operator to return the first two elements and assign them to variables:
$a,$b = '02|05|002|004|0014|0035|R'.Split('|')[0..1]
Put them to the array using select -first
$state = '02|05|002|004|0014|0035|R'
$list = #()
$list = $state.ToString().Split("|") | select -First 2
[string] $a = $list[0]
[string] $b = $list[1]
write-host $a
write-host $b