Powershell Select-String: Get results by named regex group - powershell

I have this Select-String using a regex containing a named group
$m=Select-String -pattern '(?<mylabel>error \d*)' -InputObject 'Some text Error 5 some text'
Select-String does its job:
PS > $m.Matches.groups
Groups : {0, mylabel}
Success : True
Name : 0
Captures : {0}
Index : 10
Length : 7
Value : Error 5
Success : True
Name : mylabel
Captures : {mylabel}
Index : 10
Length : 7
Value : Error 5
I can get the value of the matching named group by using the index of the group, no problem:
PS > $m.Matches.groups[1].Value
Error 5
But I have no success in getting the same result by using the named regex group (mylabel). I found statements like $m.Matches.groups["mylabel"].Value but that doesn't work on my machines (W10/W2012, PS 5.1)

You got one correct answer in the comment above, but here is how to do it without using the 0 match index:
$m.Matches.groups | ? { $_.Name -eq 'mylabel' } | Select-Object -ExpandProperty Value

Related

How to fetch the specific key value inside the collection using powershell

Given below command giving the output as object
$output = (Invoke-AzVMRunCommand -ResourceGroupName $rgname -Name $vmname -CommandId 'RunPowerShellScript' -ScriptPath authoring.ps1).value
Output
Mode : Process
ContextDirectory :
ContextFile :
CacheDirectory :
CacheFile :
Settings : {}
Code : ComponentStatus/StdOut/succeeded
Level : Info
DisplayStatus : Provisioning succeeded
Message : #{cluster_name=test01; status=green; timed_out=False; number_of_nodes=3;
number_of_data_nodes=3;
active_primary_shards=25; active_shards=50; relocating_shards=0;
initializing_shards=0;
unassigned_shards=0; delayed_unassigned_shards=0; number_of_pending_tasks=0;
number_of_in_flight_fetch=0; task_max_waiting_in_queue_millis=0;
active_shards_percent_as_number=100.0}
Time :
Code : ComponentStatus/StdErr/succeeded
Level : Info
DisplayStatus : Provisioning succeeded
How to get the Message ==> number_of_nodes = 3 and number_of_data_nodes=3 in some variable so based on this value I need to perform some action.
Thanks
Ok, if as you tested $Output.Message is a multiline string like
#{cluster_name=test01; status=green; timed_out=False; number_of_nodes=3;
number_of_data_nodes=3;
active_primary_shards=25; active_shards=50; relocating_shards=0;
initializing_shards=0;
unassigned_shards=0; delayed_unassigned_shards=0; number_of_pending_tasks=0;
number_of_in_flight_fetch=0; task_max_waiting_in_queue_millis=0;
active_shards_percent_as_number=100.0}
you can convert this into a Hashtable like this:
$data = $Output.Message.Trim("#{}") -replace ';', [environment]::NewLine | ConvertFrom-StringData
If you print that out to screen with $data | Format-Table -AutoSize it looks like this:
Name Value
---- -----
number_of_nodes 3
task_max_waiting_in_queue_millis 0
number_of_data_nodes 3
status green
initializing_shards 0
active_shards_percent_as_number 100.0
cluster_name test01
delayed_unassigned_shards 0
active_shards 50
unassigned_shards 0
active_primary_shards 25
number_of_in_flight_fetch 0
timed_out False
relocating_shards 0
number_of_pending_tasks 0
With this Hashtable format, it is easy to get the values of the different keys.
For instance:
$data.number_of_nodes # --> 3
$data.number_of_data_nodes # --> 3
$data.cluster_name # --> test01

retrieving and changing data of an object, which is in another object

passing by value or reference : powershell
more information :
PSVersion 5.1.19041.906
All files can be found here : [*]https://drive.google.com/drive/folders/1Ya0Xyxewgo6FtUHVbGqSASqXOFSlXvbR?usp=sharing
I would like to try to pass an object by reference, variable. In this object I would like to pass a bunch of information (containing different other variables/data).
Sometimes there's a need to return it back (one variable), by return $menuObjts.
At paragraphs 'INFO' are $menuObjts and $menuObjts[‘MENUS’] shown.
More information about these object I have tried to figure it out by gettype().fullname.
REMARK : in the code here I've used $global: for allowing to ACCESS and CHANGE the variable and be able to make a screenshot and use it for test purpose.
So my problem is to ACCESS and CHANCE values in $menuObjts[‘MENUS’], which is a part, element of $menuObjts.
Thanks to #Santiago Squarzon for his patience and quick reaction.
The idea is to create dynamically menus from the CSV file (what works) and calls the selected functions by name - $menus_.FUNCTION which are retrieved.
But now I would like to extend it and be able to create multi sub menus.
There are two seperate MENU_GRP elements :
$menuObjts.MENU_GRP
-- contains info about the current/active/selected one
($menuObjts.**MENUS** | Where-Object {[int]**$($_).MENU_GRP** -eq ...
-- $menuObjts.MENUS : contains all posible menus (CSV)
So I import a range menu-items by a CSV file.
So these $menus_ are added to $menuObjts.MENUS / $menuObjts[‘MENUS’]
There are other features in $menus_ such as MENU, PARENT, MENU_GRP, MENU_IDX, MENU_OFFSET, MENU_SEL_TYPE, nrElems, FUNCTION, info, status , SEL, RESTART, STOP
$global:menus_ = Import-Csv -Delimiter "," $($curPath)
$menuGRP_ = 0 # 0 - MAIN
$menus_.MENU
$nrRestarts = #($menus_ | Where-Object { [int]$_.RESTART -eq 1 -and [int]$_.MENU_GRP -eq 0 }).Count
write-host (" info : - nrRestarts: {0}" -f ($nrRestarts))
# SET : values in one object : $menuObjts
$global:menuObjts =[ordered]#{
MENUS = $menus_;
MENU_GRP = $menuGRP_;
MENU_SEL_TYPE = $null;
MENU_OFFSET = $null;
nrElems = $null;
sel_input = $null;
MENU_IDX = $null}
$menuObjts.MENUS?MENU_GRP = 0 or $menuObjts.MENUS?MENU_GRP = 6
$menuObjts.MENUS?MENU_OFFSET = -1 or $menuObjts.MENUS?MENU_OFFSET = 12
$menuObjts.MENUS?nrElems = 13 or $menuObjts.MENUS?nrElems = 4
$menuObjts.MENUS ? - ? because I don't know how to retrieve the underlying object and their features/data
So my problem is how to retrieve each element of $menus_ in $menuObjts.MENUS again.
The idea is that via one variable, the next one will be calculated ([*]see function updateMenuObjtsInfo )
So my question is how can I see by type, how to get the wanted data ...
information of variables/object Get-Variable
gettype()
$menuObjts
$menuObjts.MENUS
$menuObjts.MENUS | select -first 1
These are a few things I want to achieve, but this doesn't work proper ($_).MENU_GRP
$1stElementGrp_ = $($menus_ | Where { [int]$($_).MENU_GRP -eq $menuObjts.MENU_GRP }| Select -First 1 )
$menuOFFSET_ = $($1stElementGrp_).MENU_OFFSET
$menuNrElems_ = $($1stElementGrp_).nrElems
##### where $($menuObjts.MENUS).MENU_GRP -eq $menuObjts.MENU_GRP -> .MENU_OFFSET
$menuObjts.MENU_OFFSET = $($menuObjts.MENUS | Where-Object { [int]$($_).MENU_GRP -eq $menuObjts.MENU_GRP}| Select -First 1 ).MENU_OFFSET
$menuObjts.nrElems = #($menuObjts.MENUS | Where-Object { [int]$($_).MENU_GRP -eq $menuObjts.MENU_GRP -and [int]$($_).SEL -eq 1}).Count
Another idea … was adding methods, but I’m struggling with my (little) knowledge of Powershell.
(based on 4 Ways to Create PowerShell Objects | RidiCurious.com )
$menuObjts | Add-Member -MemberType ScriptMethod -Name "getMENUS_RESTART" -Value $( this.MENUS | Where-Object { [int]$_.RESTART -eq 1 -and [int]$_.MENU_GRP -eq $menuGRP_ })
INFO - $menuObjts :
Name Value
---- -----
MENUS {#{MENU;PARENT;MENU_GRP;MENU_IDX;MENU_OFFSET;MENU_SEL_TYPE;nrElems;FUNCTION;info;status;SEL;RESTART;STOP=typeInstallation;LICENSE;0;0;-1;0;13;f1;Windows-Defende...
MENU_GRP 0
MENU_SEL_TYPE
MENU_OFFSET
nrElems
sel_input
MENU_IDX
INFO - $menuObjts.MENUS :
MENU;PARENT;MENU_GRP;MENU_IDX;MENU_OFFSET;MENU_SEL_TYPE;nrElems;FUNCTION;info;status;SEL;RESTART;STOP
-----------------------------------------------------------------------------------------------------
typeInstallation;LICENSE;0;0;-1;0;13;f1;Windows-Defender has to be uninstalled
activate;;0;1;-1;0;13;f2;Windows has to be upgraded if working with an EVALUATION prod key;-1;0;0;0
NAME;HOST;0;2;-1;0;13;f3;F-SEC has to be configured as an isolated machine on the CSI server;-1;0;0;0
IP;;0;3;-1;0;13;f4;disable default Windows NTP service;-1;0;1;0
routes;;0;4;-1;0;13;f5;disable default Windows NTP service;-1;0;0;0
users;;0;5;-1;0;13;f6;disable default Windows NTP service;-1;0;0;0
ANTI VIRUS;SERVICEs;0;6;-1;0;13;f7;disable default Windows NTP service;-1;0;0;0
NTP;;0;7;-1;0;13;f8;;-1;0;0;0
MEINBERG;;0;8;-1;0;13;f9;;-1;0;0;0
addPATH;postgres;0;9;-1;0;13;f10;;-1;0;0;0
check;after CSI;0;10;-1;0;13;f11;;-1;0;0;0
execute;;0;11;-1;0;13;f12;;-1;0;0;1
quite;;0;12;-1;0;13;f13;;-1;0;0;1
WINDOWS DEFENDER;ANTI VIRUS;6;13;12;1;4;f14;;-1;0;0;0
F-SEC;;6;14;12;1;4;f15;;-1;0;0;0
execute;;6;15;12;1;4;f16;;-1;0;0;1
quite;;6;16;12;1;4;f17;;-1;0;0;1
Additional information [2021/05/04]
PS C:\Users\Administrator> $menuObjts.MENUS | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
FUNCTION NoteProperty string FUNCTION=f1
info NoteProperty string info=Windows-Defender has to be uninstalled, before installing an other anti-virus program
MENU NoteProperty string MENU=typeInstallation
MENU_GRP NoteProperty string MENU_GRP=0
MENU_IDX NoteProperty string MENU_IDX=0
MENU_OFFSET NoteProperty string MENU_OFFSET=-1
...
PS C:\Users\Administrator> $menuObjts.MENUS
MENU : typeInstallation
PARENT : LICENSE
MENU_GRP : 0
MENU_IDX : 0
MENU_OFFSET : -1
MENU_SEL-TYPE :
nrElems : 13
FUNCTION : f1
info : Windows-Defender has ...
status : -1
SEL : 0
RESTART : 1
STOP :
MENU : activate
PARENT :
MENU_GRP : 0
...
I have the impression that $menus_ is added as a 'value' instead as an object to $menuObjts - Value : {#{MENU=
PS C:\Users\Administrator> $menuObjts.MENUS.PSobject.Properties
ReferencedMemberName : Length
ConversionType :
MemberType : AliasProperty
TypeNameOfValue : System.Int32
IsSettable : False
IsGettable : True
Value : 17
Name : Count
IsInstance : False
MemberType : Property
Value : 17
IsSettable : False
IsGettable : True
TypeNameOfValue : System.Int32
Name : Length
IsInstance : True
...
MemberType : Property
Value : {#{MENU=typeInstallation; PARENT=LICENSE; MENU_GRP=0; MENU_IDX=0; MENU_OFFSET=-1; MENU_SEL-TYPE=; nrElems=13;FUNCTION=f1; info=Windows-Defender has to be uninstalled, before installing an other anti-virus program;status=-1; SEL=0; RESTART=1; STOP=},
#{MENU=activate; PARENT=; MENU_GRP=0; MENU_IDX=1; MENU_OFFSET=-1; MENU_SEL-TYPE=; nrElems=13; FUNCTION=f2; info=Windows has to be upgraded if working with an EVALUATION prod key;status=-1; SEL=0; RESTART=0; STOP=},
#{MENU=NAME; PARENT=HOST; MENU_GRP=0; MENU_IDX=2; MENU_OFFSET=-1;MENU_SEL-TYPE=; nrElems=13; FUNCTION=f3; info=F-SEC has to be configured as an isolated machine on the CSI server;status=-1; SEL=0; RESTART=0; STOP=},
#{MENU=IP; PARENT=; MENU_GRP=0; MENU_IDX=3; MENU_OFFSET=-1; MENU_SEL-TYPE=;nrElems=13; FUNCTION=f4; info=disable default Windows NTP service; status=-1; SEL=0; RESTART=1; STOP=}...}
IsSettable : False
IsGettable : True
TypeNameOfValue : System.Object
Name : SyncRoot
IsInstance : True
...
First of all, I would recommend a good read on: Where-Object, about_Arrays and this good article on PS Objects
# Storing the CSV in the $csv var
$csv = #'
MENU;PARENT;MENU_GRP;MENU_IDX;MENU_OFFSET;MENU_SEL_TYPE;nrElems;FUNCTION;info;status;SEL;RESTART;STOP
typeInstallation;LICENSE;0;0;-1;0;13;f1;Windows-Defender has to be uninstalled
activate;;0;1;-1;0;13;f2;Windows has to be upgraded if working with an EVALUATION prod key;-1;0;0;0
NAME;HOST;0;2;-1;0;13;f3;F-SEC has to be configured as an isolated machine on the CSI server;-1;0;0;0
IP;;0;3;-1;0;13;f4;disable default Windows NTP service;-1;0;1;0
routes;;0;4;-1;0;13;f5;disable default Windows NTP service;-1;0;0;0
users;;0;5;-1;0;13;f6;disable default Windows NTP service;-1;0;0;0
ANTI VIRUS;SERVICEs;0;6;-1;0;13;f7;disable default Windows NTP service;-1;0;0;0
NTP;;0;7;-1;0;13;f8;;-1;0;0;0
MEINBERG;;0;8;-1;0;13;f9;;-1;0;0;0
addPATH;postgres;0;9;-1;0;13;f10;;-1;0;0;0
check;after CSI;0;10;-1;0;13;f11;;-1;0;0;0
execute;;0;11;-1;0;13;f12;;-1;0;0;1
quite;;0;12;-1;0;13;f13;;-1;0;0;1
WINDOWS DEFENDER;ANTI VIRUS;6;13;12;1;4;f14;;-1;0;0;0
F-SEC;;6;14;12;1;4;f15;;-1;0;0;0
execute;;6;15;12;1;4;f16;;-1;0;0;1
quite;;6;16;12;1;4;f17;;-1;0;0;1
'#|convertfrom-csv -Delimiter ';'
Get the first element of the array
$1stElementGrp_ = $csv[0] # Like this
$1stElementGrp_ = $csv | Select-Object -First 1 # Or Like this
Get the value of the property MENU_OFFSET and nrElems of the variable $1stElementGrp_
$menuOFFSET_ = $1stElementGrp_.MENU_OFFSET # $menuOFFSET_ returns -1
$menuNrElems_ = $1stElementGrp_.nrElems # $menuNrElems_ returns 13
Not sure what you're trying filter here
# $menuObjts.MENU_OFFSET = ($menuObjts.MENUS | Where-Object {
# [int]$($_).MENU_GRP -eq $menuObjts.MENU_GRP
# }| Select -First 1).MENU_OFFSET
#
# $menuObjts.nrElems = #($menuObjts.MENUS | Where-Object {
# [int]$($_).MENU_GRP -eq $menuObjts.MENU_GRP -and [int]$($_).SEL -eq 1}).Count
# }
Example: If you want to filter all the rows where MENU_OFFSET = -1
$csv | Where-Object {$_.MENU_OFFSET -eq -1} |
Select-Object MENU, PARENT, MENU_GRP, MENU_IDX, MENU_OFFSET |
Format-Table
Returns
MENU PARENT MENU_GRP MENU_IDX MENU_OFFSET
---- ------ -------- -------- -----------
typeInstallation LICENSE 0 0 -1
activate 0 1 -1
NAME HOST 0 2 -1
IP 0 3 -1
routes 0 4 -1
users 0 5 -1
ANTI VIRUS SERVICEs 0 6 -1
NTP 0 7 -1
MEINBERG 0 8 -1
addPATH postgres 0 9 -1
check after CSI 0 10 -1
execute 0 11 -1
quite 0 12 -1
Example: If you want to filter all the rows where MENU_GRP = 6 AND MENU matches the word 'WINDOWS'
$csv | Where-Object {$_.MENU_GRP -eq 6 -and $_.MENU -match 'Windows'} |
Select-Object MENU, PARENT, MENU_GRP, MENU_IDX, MENU_OFFSET |
Format-Table
Returns:
MENU PARENT MENU_GRP MENU_IDX MENU_OFFSET
---- ------ -------- -------- -----------
WINDOWS DEFENDER ANTI VIRUS 6 13 12

How do I iterate through JSON array in powershell

How do I iterate through JSON array which is converted to PSCustomObject with ConvertFrom-JSON? Using foreach does not work.
$jsonArray ='[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'
$json = convertfrom-json $jsonArray
$json | foreach {$_}
Returns
privateKeyLocation
------------------
C:\ProgramData\docker\certs.d\key.pem
Enumerator though says there are 3 members of array
>$json.Count
3
The problem that you are having is not specific to it being a JSON array, it has to do with how custom objects in an array are displayed by default. The simplest answer is to pipe it to Format-List (or FL for short).
PS C:\Users\TMTech> $JSON|FL
privateKeyLocation : C:\ProgramData\docker\certs.d\key.pem
publicKeyLocation : C:\ProgramData\docker\certs.d\cert.pem
publicKeyCALocation : C:\ProgramData\docker\certs.d\ca.pem
Aside from that, when PowerShell outputs an array of objects it bases the columns that it displays upon the properties of the first object in the array. In your case that object has one property named 'privateKeyLocation', so that is the only column that appears, and since the other two objects do not have that property it does not display anything for them. If you want to keep it as a table you could gather all potential properties, and add them to the first item with null values, and that would allow you to display it as a table, but it still wouldn't look very good:
$json|%{$_.psobject.properties.name}|select -Unique|?{$_ -notin $json[0].psobject.Properties.Name}|%{Add-Member -InputObject $JSON[0] -NotePropertyName $_ -NotePropertyValue $null}
Then you can output as a table and get everything:
PS C:\Users\TMTech> $json
privateKeyLocation publicKeyLocation publicKeyCALocation
------------------ ----------------- -------------------
C:\ProgramData\docker\certs.d\key.pem
C:\ProgramData\docker\certs.d\cert.pem
C:\ProgramData\docker\certs.d\ca.pem
Edit: To get the value of each object in this case is tricky, because the property that you want to expand keeps changing for each object. There's two ways to do this that I can think of, what I would consider the right way, and then there's the easy way. The right way to do it would be to determine the property that you want to expand, and then reference that property directly:
$JSON |%{
$PropName = $_.PSObject.Properties.Name
$_.$PropName
}
That'll do what you want, but I think easier would be to pipe to Format-List, then Out-String, wrap the whole thing in parenthesis, split on new lines and replace everything up to : which should just leave you with the paths you want.
($JSON|FL|Out-String) -split '[\r\n]+' -replace '(?m)^.+ : '|?{$_}
Interesting enough. I responded to this exact question from the same OP on another forum. Though my response was just RegEx and be done with it, with no additional conversion.
Of course there are several ways to do this. The below is just what I came up with.
$jsonArray = '[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'
([regex]::Matches($jsonArray,'(?<=\").:\\[^\"]+(?=\")').Value) -replace '\\\\','\' `
| ForEach {
If (Test-Path -Path $_)
{"path $_ found"}
Else {Write-Warning "Path $_ not found"}
}
WARNING: Path C:\ProgramData\docker\certs.d\key.pem not found
WARNING: Path C:\ProgramData\docker\certs.d\cert.pem not found
WARNING: Path C:\ProgramData\docker\certs.d\ca.pem not found
So, maybe not as elegant as what was posted here, but it would get the OP where they wanted to be.
So, consolidating everything TheMadTechnician gave and what the OP is after, and attempting to make it as concise as possible, would give the OP the below (I added a element to show a positive response):
Clear-Host
($jsonArray = #'
[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"},
{"publicKeyTestFileLocation" : "D:\\Temp\\test.txt"}]
'# | ConvertFrom-Json | Format-List | Out-String) -split '[\r\n]+' -replace '(?m)^.+ : '`
| Where-Object {$_} | ForEach {
If(Test-Path -Path $_){"The path $_ was found"}
Else{Write-Warning -Message "The path $_ was not found}"}
}
WARNING: The path C:\ProgramData\docker\certs.d\key.pem was not found}
WARNING: The path C:\ProgramData\docker\certs.d\cert.pem was not found}
WARNING: The path C:\ProgramData\docker\certs.d\ca.pem was not found}
The path D:\Temp\test.txt was found
Which one is more to his liking is a matter of the OP choice of course.
The performance between the two varied on each test run, but the fastest time using the straight RegEx approach was:
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 43
Ticks : 439652
TotalDays : 5.08856481481481E-07
TotalHours : 1.22125555555556E-05
TotalMinutes : 0.000732753333333333
TotalSeconds : 0.0439652
TotalMilliseconds : 43.9652
and the fastest on the consolidated version here was:
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 54
Ticks : 547810
TotalDays : 6.34039351851852E-07
TotalHours : 1.52169444444444E-05
TotalMinutes : 0.000913016666666667
TotalSeconds : 0.054781
TotalMilliseconds : 54.781
Updating to add iRon's take on this topic
So this...
$jsonArray ='[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'
$json = convertfrom-json $jsonArray
$json | ForEach {
$Key = $_.psobject.properties.name;
"Testing for key " + $_.$Key
Test-Path -Path $_.$Key
}
Testing for key C:\ProgramData\docker\certs.d\key.pem
False
Testing for key C:\ProgramData\docker\certs.d\cert.pem
False
Testing for key C:\ProgramData\docker\certs.d\ca.pem
False
... and this:
('[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]' `
| convertfrom-json) | ForEach {
$Key = $_.psobject.properties.name;
"Testing for key " + $_.$Key
Test-Path -Path $_.$Key
}
Testing for key C:\ProgramData\docker\certs.d\key.pem
False
Testing for key C:\ProgramData\docker\certs.d\cert.pem
False
Testing for key C:\ProgramData\docker\certs.d\ca.pem
False
Most simple way, should be like this
$ret ='[your json]'
$ret | ConvertFrom-Json
$data = $ret | ConvertFrom-Json
foreach($data in $ret | ConvertFrom-Json) {
Write-Host $data;
}
You can index into the array. Check out $json.GetType()
$jsonArray ='[{"privateKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\key.pem"},
{"publicKeyLocation" : "C:\\ProgramData\\docker\\certs.d\\cert.pem"},
{"publicKeyCALocation" : "C:\\ProgramData\\docker\\certs.d\\ca.pem"}]'
$json = convertfrom-json $jsonArray
foreach($i in 0..($json.Count-1)){
$json[$i] | out-host
$i++
}
You can use ForEach-Object i.e:
$json | ForEach-Object -Process { Write-Hoste $_; }
That's I believe the simplest way and gives you easy access to properties if array contains objects with other properties.

Throwing error intermittently

I am getting a weird error, and that too sometimes while executing my script. The error is:
Method invocation failed because [System.Object[]] does not contain a method named 'op_Subtraction'.
The line in which I get this error is:
$LineNr = $dbsnap_file | Select-String -Pattern $check | Select-Object -ExpandProperty LineNumber
$del = $dbsnap_file[$LineNr-13] -split ':' | Select-Object -Last 1
$dbsnap_file is gc (some_file). That file contents are like:
AllocatedStorage : 5
AvailabilityZone : us-west-1a
DBInstanceIdentifier : test-multisite
DBSnapshotIdentifier : test-multisite-2015-09-03-04-15
Encrypted : False
Engine : mysql
EngineVersion : 5.6.19a
InstanceCreateTime : 12/19/2014 5:19:26 AM
Iops : 0
KmsKeyId :
LicenseModel : general-public-license
MasterUsername : root
OptionGroupName : default:mysql-5-6
PercentProgress : 100
Port : 3306
SnapshotCreateTime : 9/2/2015 11:15:36 PM
SnapshotType : automated
$check has value like test-multisite-2015-09-03-04-15. So, what I get as $del is the SnapshotCreateTime.
Iam recieving this error intermittently, sometimes its working, sometimes not. Can someone please guide me through what will be the issue.?
Like CB was saying Select-String will return all matches. You were expecting only one and the code was built around that assumption. The error you are getting is fairly explicit.
[System.Object[]] does not contain a method named 'op_Subtraction'
You were trying to subtract 13 from an object instead of an integer. As discussed in chat it turned out the issue was your source file had a double of data.
The solution in this case was to clean your source. If you are comfortable with assumptions you can also address this issue by updating the select
$LineNr = $dbsnap_file | Select-String -Pattern $check | Select-Object -First 1 -ExpandProperty LineNumber
That will ensure only one is returned. Caveat being you are ignoring real data. So verify the source and the contents of the $LineNr are the solutions I would recommend here.

PowerShell Cmdlets .length attribute for one element result

I am using a Cmdlet which can return one or more elements:
PS C:\Users\admin> $x = Get-myObjects
PS C:\Users\admin> $x
ComputerName : test-2
Description : n/a
Id : cbcb1ece-99f5-4478-9f02-65a622df8a98
IsActive :
MinNum : 0
Name : scom-test2-mp
modeType : 1
PSComputerName :
If I use length attribute I get nothing.
PS C:\Users\admin> $x.length
PS C:\Users\admin>
Yet, if the Get-myObjects cmdlet returns 2 or more, then it is a collection and I can get .length attribute.
How can I get the .length to work if the Get-myObjects cmdlet returns a single object for one object value?
You can always force the result into an array, either when assigning the return value of your cmdlet to a variable:
$x = #(Get-myObjects)
$x.Length
or "on-demand":
$x = Get-myObjects
#($x).Length
Use the Measure-Object cmdlet. It's a little clunky here because you can't just get the count in an elegant way.
$x = Get-myObjects
$x | measure-object
Output:
Count : 1
Average :
Sum :
Maximum :
Minimum :
Property :
If you just want the count:
$x | measure-object | select -ExpandProperty Count
Output:
1
I noticed that in this case it is better to use the foreach loop of powershell.
reference of logical loops in PowerShell
example:
foreach($i in $x)
{
Write-Host $i.Name
}
The above example works for both when $x has one element or more.