I have two arrays. One that is an import from a CSV and the second is a list of items and id numbers. My goal is to compare one of the columns in the CSV to the second array. When it finds a match, i would like it to return the index of the second array so i can insert the items ID number in future lines of code.
I have tried to use .IndexOf but since i am comparing it to another array, it does not find the value. The values of "NewPhaseName" can be different when the program runs and the NewPhaseNumber is generated during runtime as well. My script currently takes a CSV file, searches for UniquePhaseNames, sends those names through an API to generate a NewPhaseNumber. I then need to use that NewPhaseNumber later in my script for another API call.
$NewPhaseName = "Plan", "Test", "Deploy"
$NewPhaseNumber = "1077", "1089", "1100"
$Ticket.PhaseDescription[1] = "Plan"
$Ticket.PhaseDescription[2] = "Plan"
$Ticket.PhaseDescription[3] = "Deploy"
$PhaseIndex = $Ticket.PhaseDescription.IndexOf($NewPhaseName)
$NewPhaseIndex = $NewPhaseNumber[$PhaseIndex]
What i am hoping to get would be
$NewPhaseIndex[0] = 1077
$NewPhaseIndex[1] = 1077
$NewPhaseIndex[2] = 1100
Thank you
I suggest to reorganize your data structure, or build a hash table from
$NewPhaseName = "Plan", "Test", "Deploy"
$NewPhaseNumber = "1077", "1089", "1100"
$hash = #{}
for($i=0;$i -lt $newPhaseName.Count; $i++){
$hash[$NewPhaseName[$i]]=$NewPhaseNumber[$i]
}
$hash
yielding:
> $hash
Name Value
---- -----
Plan 1077
Deploy 1100
Test 1089
# simulate Ticket array
$Ticket = #"
PhaseDescription
"Plan"
"Plan"
"Deploy"
"# -split '\r?\n' | ConvertFrom-Csv
# Append new column with NewPhaseIndex looked up from $hash
$Ticket | Select-Object *,#{n='NewPhaseIndex';e={$hash[$PhaseDescriptiom]}}
PhaseDescription NewPhaseIndex
---------------- -------------
Plan 1077
Plan 1077
Deploy 1100
I'm coding with PowerShell and want to output a whole array at once. Is that possible?
I need to output a SQL table and don't wanna say $reader[1..20]
Write-Host $reader[0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]
I don't wanna say a number like $reader[2..3] I wanna output the whole array at once like $reader[*]
You could use StringBuilder:
$sb= [System.Text.StringBuilder]::new()
$reader | % { $sb.Append($_) }
Write-Host ($sb.ToString())
Or use the join operator. For example, join an array and dump every entry on a separate line:
$text = #("a", "b", "c")
Write-Host ($text -join "`n")
How are you populating $reader?
If you are just outputting to the screen, that is the PowerShell default, so no real need for the Write-*.
[array]$reader = 0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
# Or
$reader = #(0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31)
$reader
# Result
0
1
2
3
4
5
...
$reader[3]
# Result
3
$reader[0..3]
# Result
0
1
2
3
I have the following code which works but I am looking for a way to do this all inline without the need for creating the unnecessary variables $myArray1 and $myArray2:
$line = "20190208 10:05:00,Source,Severity,deadlock victim=process0a123b4";
$myArray1 = $line.split(",");
$myArray2 = $myArray1[3].split("=");
$requiredValue = $myArray2[1];
So I have a string $line which I want to:
split by commas into an array.
take the fourth item [3] of the new array
split this by the equals sign into another array
take the second item of this array [1]
and store the string value in a variable.
I have tried using Select -index but I haven't been able to then pipe the result and split it again.
The following works:
$line.split(",") | Select -index 3
However, the following results in an error:
$line.split(",") | Select -index 3 | $_.split("=") | Select -index 1
Error message: Expressions are only allowed as the first element of a pipeline.
$line.Split(',')[3].Split('=')[1]
Try below code:
$requiredValue = "20190208 10:05:00,Source,Severity,deadlock victim=process0a123b4" -split "," -split "=" | select -Last 1
Mudit already provided an answer, here's another about your particular case.
Piping to foreach and accessing 2nd element does the trick:
$line.split(",") | Select -index 3 | % {$_.split("=")[1]}
process0a123b4
That being said, aim for readability and ease of maintenance. There's nothing wrong with having intermediate variables. Memory is cheap nowadays, programmers' time is not. Optimization is due when it's needed and only then after careful profiling to see what's the actual bottleneck.
You could pipe the second split to a foreach
$line.split(",") | Select -index 3 | foreach { $_.split("=") | Select -index 1 }
OK, Powershell may not be the best tool for the job but it's the only one available to me.
I have a bunch of 600K+ row .csv data files. Some of them have delimiter errors e.g. " in the middle of a text field or "" at the start of one. They are too big to edit (even in UltraEdit) and fix manually even if I wanted to which I don't!
Because the double-""-delimeter at the start of some text fields and rogue-"-delimiter in the middle of some text fields, I haven't used a header row to define the columns because these rows appear as if there is an extra column in them due to the extra delimiter.
I need to parse the file looking for "" instead of " at the start of a text-field and also to look for " in the middle of a text field and remove them.
I have managed to write the code to do this (after a fashion) by basically reading the whole file into an array, looping through it and adding output characters to an output array.
What I haven't managed to do is successfully write this output array to a file.
I have read every part of https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Utility/out-file?view=powershell-5.1 that seemed relevant. I've also trawled through about 10 similar questions on this site and attempted various code gleaned from them.
The output array prints perfectly to screen using a Write-Host but I can't get the data back into a file for love or money. I have a total of 1.5days Powershell experience so far! All suggestions gratefully received.
Here is my code to read/identify rogue delimiters (not pretty (at all), refer previous explanation of data and available technology constraints):
$ContentToCheck=get-content 'myfile.csv' | foreach { $_.ToCharArray()}
$ContentOutputArray=#()
for ($i = 0; $i -lt $ContentToCheck.count; $i++)
{
if (!($ContentToCheck[$i] -match '"')) {#not a quote
if (!($ContentToCheck[$i] -match ',')) {#not a comma i.e. other char that could be enclosed in ""
if ($ContentToCheck[$i-1] -match '"' ) {#check not rogue " delimiter in previous char allow for start of file exception i>1?
if (!($ContentToCheck[$i-2] -match ',') -and !($ContentToCheck[$i-3] -match '"')){
Write-Host 'Delimiter error' $i
$ContentOutputArray+= ''
}#endif not preceded by ",
}#endif"
else{#previous char not a " so move on
$ContentOutputArray+= $ContentToCheck[$i]
}
}#endifnotacomma
else
{#a comma, include it
$ContentOutputArray+= $ContentToCheck[$i]
}#endacomma
}#endifnotaquote
else
{#a quote so just append it to the output array
$ContentOutputArray+= $ContentToCheck[$i]
}#endaquote
}#endfor
So far so good, if inelegant. if I do a simple
Write-Host $ContentOutputArray
data displays nicely " 6 5 " , " 652 | | 999 " , " 99 " , " " , " 678 | | 1 " ..... furthermore when I check the size of the array (based on a cut-down version of one of the problem files)
$ContentOutputArray.count
I get 2507 character length of array. Happy out. However, then variously using:
$ContentOutputArray | Set-Content 'myfile_FIXED.csv'
creates blank file
$ContentOutputArray | out-file 'myfile_FIXED.csv' -encoding ASCII
creates blank file
$ContentOutputArray | export-csv 'myfile_FIXED.csv'
gives only '#TYPE System.Char' in file
$ContentOutputArray | Export-Csv 'myfile_FIXED.csv' -NoType
gives empty file
$ContentOutputArray >> 'myfile_FIXED.csv'
gives blanks separated by ,
What else can I try to write an array of characters to a flat file? It seems such a basic question but it has me stumped. Thanks for reading.
Convert (or cast) the char array to a string before exporting it.
(New-Object string (,$ContentOutputArray)) |Set-Content myfile_FIXED.csv
I wondering if there's a way to store/retrieve data in a hash table or an array. For instance,
$a = get-process
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id SI ProcessName
------- ------ ----- ----- ----- ------ -- -- -----------
156 9 1924 220 ...23 0.06 3788 4 ActionUriServer
364 19 10676 22196 ...01 0.75 11432 4 ApplicationFrameHost
155 9 6360 10388 ...98 5.47 14940 0 audiodg
I need this to be stored in a variable. When I want this to be retried, I should be able to use the index value.
for e.g. $a[1][1] should fetch me the value 'Handles'
I roughly have an idea about multi dimensional arrays, but then, not really sure how to push these values to the variable and have it indexed.
will foreach workout ?
If you really want to parse the formatted output rather than operate on the objects returned by Get-Process (or customize formatting using one of the Format-* cmdlets), you can try this:
Get-Process | Out-String -Stream | % { $a = #() } { $a += $null; $a[-1] = -split $_ }
Out-String -Stream is required to obtain the formatted-for-output string representations of the objects returned by Get-Process, and -Stream passes each resulting line individually through the pipeline (by default, Out-String passes the entire resulting string at once).
The above is simple, but not efficient, because the array is recreated for each input line; to remedy that, you could use a [System.Collections.Generic.List[string[]]] instance instead.
PowerShell arrays are 0-based, so it'll be $a[1][0] that contains Handles
(The reason that it is row 1 is that the formatted output starts with a blank line, but that could easily be fixed.)