When piping array of integers the $_ variable is null? - powershell

Take this as an example:
$var = "one","two","three"
0..2 | select-object $var[$_]
Index operation failed; the array index evaluated to null.
At line:1 char:27
+ 0..2 | select-object $var[ <<<< $_]
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
Why is $_ a null?

I can't figure why you are using select-object
try this:
$var = "one","two","three"
0..2 | % { $var[$_]}

You can also use select-object in a different way:
$var | select -Index (0..2)
And btw, if all you want to do is extract element in the array, you can do array slicing:
$var[0..2]

If you want to use select-object you need to create a hashtable, aka calculated property, and give it a name and expression keys. The result would be objects with one property, var, in the following example
0..2 | select #{name='var';expression={$var[$_]}}
var
---
one
two
three

Related

Is there a reason my Powershell script is now returning null-value expression errors?

As the title suggests, I have a script that I've been running daily to parse tables from a web page and export those to a csv. A few days ago though, I realized the script has been returning the following errors:
You cannot call a method on a null-valued expression. At C:\Users\Luke\DailyStats\NHLStats.ps1:16 char:1
+ $headers = $rows.item(1).children | select -ExpandProperty InnerText
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull Cannot index into a null array. At C:\Users\Luke\DailyStats\NHLStats.ps1:23 char:14
+ $headers = #($headers[0];'TEAM';$headers[1..($headers.Length-1)])
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray Cannot index into a null array. At C:\Users\Luke\DailyStats\NHLStats.ps1:23 char:33
+ $headers = #($headers[0];'TEAM';$headers[1..($headers.Length-1)])
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
I don't get why all of a sudden it randomly stopped working. Any and all help is greatly appreciated.
My script:
$url = "https://www.hockey-reference.com/leagues/NHL_2020.html"
#getting the data
$data = Invoke-WebRequest $url
#grab the third table
$table = $data.ParsedHtml.getElementsByTagName("table") | Select -skip 2 | Select -First 1
#get the rows of the Team Statistics table
$rows = $table.rows
#get table headers
$headers = $rows.item(1).children | select -ExpandProperty InnerText
#$headers = $headers | % { if ($_ -eq "GF") { "GFPG" } else { $_ }}
#count the number of rows
$NumOfRows = $rows | Measure-Object
#Manually injecting TEAM header and replace any headers you want to change
$headers = #($headers[0];'TEAM';$headers[1..($headers.Length-1)])
#enumerate the remaining rows (we need to skip the header row) and create a custom object
$allData = #{}
$out = for ($i=2;$i -lt $NumofRows.Count;$i++) {
#define an empty hashtable
$objHash=[ordered]#{}
#getting the child rows
$rowdata = $rows.item($i).children | select -ExpandProperty InnerText
for ($j=0;$j -lt $headers.count;$j++) {
#add each row of data to the hash table using the correlated table header value
$objHash[$headers[$j]] = $rowdata[$j]
}
#turn the hashtable into a custom object
[pscustomobject]$objHash
$allData.Add($i, $objHash)
}
$out | Select TEAM,AvAge,GP,W,L,OL,PTS,PTS%,GF,GA,SOW,SOL,SRS,SOS,TG/G,EVGF,EVGA,PP,PPO,PP%,PPA,PPOA,PK%,SH,SHA,PIM/G,oPIM/G,S,S%,SA,SV%,SO -SkipLast 1 | Export-Csv -Path "C:\Users\Luke\DailyStats\$((Get-Date).ToString("'NHL Stats' yyyy-MM-dd")).csv" -NoTypeInformation
Looks like your $table variable is returning null. When running that |select -skip 2 | select -first 1, it isn't returning any data to the $table variable.
This seems to be related to the -skip 2 selection.
When running just the portion of the $table = $data.ParsedHtml...
It only returns two objects.
So possibly you need to update your selection to properly retrieve the table that you want?
I am only seeing the 'standings EAS' and 'standings WES' tables being pulled.

I can't get Powershell StartsWith function to work

I'm trying to create a Powershell script that prints out only certain AD groups from the Folder Permission settings. However for some reason Powershell doesn't recognize StartsWith function.
("C:\folder" | get-acl).Access | ForEach-Object { if (($_.IdentityReference).StartsWith("sl_test")) { continue }; $_ }
When I run this I got errors similar to this for every foreach object:
Method invocation failed because [System.Security.Principal.NTAccount] does not contain a method named 'StartsWith'.
At C:\temp\test.ps1:1 char:56
+ ("C:\folder" | get-acl).Access | ForEach-Object { if (($_.IdentityReference).St ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Any suggestions on how to get this to work?
IdentityReference is a [System.Security.Principal.NTAccount]according to your error message.
But .StartWith is a method on the String type. If you call a method, Powershell does no magic for you, AFAIK.
Try ... ($_.IdentityReference) -match "^sl_test" ..., which should do the implicit string conversion.
If you want the string representation of an IdentityReference (regardless of whether it's and NTAccount object or a SID), you can reference the Value property:
$_.IdentityReference.Value.StartsWith('sl_test')
Try:
Get-Acl -Path "C:\folder" | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "sl_test*" }
You can customize the output with an additional | Select-Object -Property XY

Substring Function don't work with a variable

I need the first 3 bytes of a string. My code gets an error.
# This Code don't work
$folderoutput="Z:\Home\Chronos\" + $datum.Month;
$test = Get-ChildItem -Path $folderinput| select name, state -last 1
$test.Substring(0,3)
# This Code work
$folderoutput="Z:\Home\Chronos\" + "11"
$test = Get-ChildItem -Path $folderinput| select name, state -last 1
$test.Substring(0,3)
Error:
Method invocation failed because [Selected.System.IO.FileInfo] does
not contain a method named 'Substring'. At Z:\skript\uebung1.ps1:16
char:1
+ $test.Substring(0,3)
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (Substring:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
What is the reason for the error?
Your $test variable references not a String but an object composed from the Name and State properties of the returned FileInfo instance. There is no Substring method on this composed object (nor on a FileInfo, for that matter), hence the error. To get the name of the file you need to access the Name property, like so...
$test.Name.Substring(0, 3)
Alternatively, if you only want the Name property (not sure where State comes from) you could use the -ExpandProperty parameter to retrieve only that one value...
$test = Get-ChildItem -Path $folderinput| select -ExpandProperty name -last 1
$test.Substring(0, 3)
As for why one snippet works and the other doesn't, that's unclear. The only difference between the two is the value of $folderoutput, which is not used; on the following line you pass $folderinput to Get-ChildItem. Are you sure $datum is set and has a Month property?

Find key in hash table (ContainsKey) not working

I'm loading a hash table with this:
$htA = dir | Where-Object {$_.Name -match "\.output\.[A-Z]-[0-9]\.csv"} | select name,length
When I try to search the Key column like thusly:
$htA.ContainsKey($h.name)
I get this super neat-o error:
Method invocation failed because [Selected.System.IO.FileInfo] does not contain a method named 'ContainsKey'.
At line:3 char:9
IF ($htA.ContainsKey($h.name) -eq $false) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (ContainsKey:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound**
So is this not a legit hashtable?
$htA is created as the type cast to it, in this case System.IO.FileInfo. Try this:
$htA = #{} # Initialises as an empty hash table
foreach ($file in (dir | Where-Object {$_.Name -match "\.output\.[A-Z]-[0-9]\.csv"} | select name,length))
{
$htA.Add($file.name, $file.length) # Populate hash table
}

Get hashtable value by key of group object under strict mode version 2?

The following script, which pivot the array list by x and y, doesn't work. ($hashvariable.x not working). How to rewrite it? It seems it's not easy to simple get a value by key in a hashtable under strict mode.
Set-StrictMode -version 2 # change 2 to 1 will work
$a = #('a','b','x',10),
#('a','b','y',20),
#('c','e','x',50),
#('c','e','y',30)
$a | %{
new-object PsObject -prop #{"label" = "'$($_[0])','$($_[1])'"; value=#{ $_[2]=$_[3]}}
} |
group label | % {
"$($_.Name), $($_.Group.value.x), $($_.Group.value.y)" # error
#"$($_.Name), $($_.Group.value['x']), $($_.Group.value['y'])" # empty for x,y
}
Expected result.
'a','b', 10, 20
'c','e', 50, 30
Error:
Property 'x' cannot be found on this object. Make sure that it exists.
At line:6 char:35
+ "[$(#($_.Name -split ",") + #($_.Group.value.x, $_.Group.value.y))]"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
+ FullyQualifiedErrorId : PropertyNotFoundStrict
Not sure what you really want, but this is my best guess. You should accumulate all objects in one group in single Hashtable object instead of creating separate Hashtable for each input object:
$a = ('a','b','x',10),
('a','b','y',20),
('c','e','x',50),
('c','e','y',30)
$a |
Group-Object {$_[0]},{$_[1]} |
Select-Object Values,
#{
Name='Group'
Expression={
$_.Group |
ForEach-Object {$t=#{}}{$t.Add($_[2],$_[3])}{$t}
}
} |
ForEach-Object {
'''{0}'',''{1}'', {2}, {3}'-f#($_.Values;$_.Group['x','y'])
}
It is difficult to understand what, in fact, this script does, anyway, the problem is that only first element in a collection $_.Group.Value has the property 'x', at the same time, strict mode prohibits references to non-existent properties of an object, so you receive this error.
Here is a solution, hope I've understood right what you want:
$a = #('a','b','x',10),
#('a','b','y',20),
#('c','e','x',50),
#('c','e','y',30)
$hashtable = #{}
$a |%{
$hashtable["$($_[0]) $($_[1])"] +=
[hashtable]#{$_[2] = $_[3]}
}
$hashtable.GetEnumerator() | %{
"$($_.Key) $($_.Value['x']) $($_.Value['y'])"
}