This is a PowerShell question, sorry if it wound up in the wrong place.
I have a data file which I will call PS_Upgrade_Data. It has 6 items in it listed like this:
item1=item-2=item.3=item 4=item5=item6
Please note that items 2 through 4 are written that way due to the data coming in over which I have no control. There is a dash in item2, a period in intem3 and a space in item4 just to be clear. Items 1, 5, and 6 have nothing between the word item and the number.
I am using the follow PS line to read the data in from the file:
Get-Content "P:\PS_Upgrade_Data.txt" | Where-Object {$_.length -gt 0} | Where-Object {!$_.StartsWith("#")} | Foreach-Object -begin {$count1=0} -process {$var = $_.Split('=',6).Trim()}
This does read the data from the file in ok.
I want to take that data and drop it into six (6) different variables and I tried a foreach loop like the one below:
$count1 = 0
ForEach ($item in $var) {
Write-Host "`n"
Write-Host "count = " , $count1
if($count1 = 0) {
Write-Host "UserInit"
$UserInit = $item
}
elseif ($count1 = 1) {
Write-Host "UserInit"
$TicketNumber = $item
}
elseif ($count1 = 2) {
Write-Host "UserInit"
$UpgradeVersion = $item
}
elseif ($count1 = 3) {
Write-Host "UserInit"
$ClientName = $item
}
elseif ($count1 = 4) {
Write-Host "UserInit"
$InstName = $item
}
elseif ($count1 = 5) {
Write-Host "UserInit"
$Coffee = $item
}
$count1 +=1
}
The problem is that the counter is jumping from 0 (zero) to two (2) and then wont increase and I have no idea why.
What stupid thing am I doing or missing?
Thanks for any help.
PowerShell's assignment operator = supports multiple assignment targets per operation, so you can skip the counter and foreach loop and instead, simply do:
Get-Content "P:\PS_Upgrade_Data.txt" | Where-Object {$_.length -gt 0} | Where-Object {!$_.StartsWith("#")} | Foreach-Object {
$UserInit,$TicketNumber,$UpgradeVersion,$ClientName,$InstName,$Coffee = $_.Split('=',6).Trim()
# do with your variables what you want here
}
When I get email delegation I do it like this
If ($Delegate.count -eq 0) {
$Result = [PSCustomObject]#{
PrimaryEmail = $SourceEmail
Delegate = "None"
}
$resultsEmail += $Result
}
Else {
Foreach ($user in $Delegate) {
$Result = [PSCustomObject]#{
PrimaryEmail = $SourceEmail
Delegate = $user.DelegateAddress
}
$resultsEmail += $Result
}
}
I would like to also get Calendar delegation and add it. The problem is it is two separate amounts of information. Either can be various amounts.
Foreach ($user in $DelegateCalendarl) {
$Result = [PSCustomObject]#{
CalendarDelegateEmail = $DelegateCalendar.'scope.value'
CalendarRole = $DelegateCalendar.role
CalendarDelegateType = $DelegateCalendar.'scope.type'
}
$ResultsCal += $Result
The end out out would be a nice table like
PrimaryEmail | Delegate | CalendarDelegateEmail | CalendarRole | CalendarDelegateType
user#email Delagate#email Delagate#email manager user
user#email "" Delagate2#email Reader user
How can I combine both Results into one nice table csv file out like this example above?
(I know how to output them separately )
This is what I did. Not pretty but it works.
$SourceEmail = 'test#email.com'
[array]$DelegateEmail = gam user $SourceEmail print delegates | ConvertFrom-Csv
[array]$DelegateCalendar = gam calendar $SourceEmail print acls | ConvertFrom-Csv
[int]$max = $DelegateCalendar.Count
if ([int]$DelegateEmail.count -gt [int]$DelegateCalendar.count) { $max = $DelegateEmail.Count; }
$Output = #()
$Result = $null
If ($DelegateEmail.count -eq 0) {$mailD = "None"}
If ($DelegateEmail.count -eq 1) {$mailD = $DelegateEmail.DelegateAddress}
for ( $i = 0; $i -lt $max; $i++) {
If ($DelegateEmail.count -eq 0 -and $i -ige 1) {$mailD = ""}
If ($DelegateEmail.count -eq 1 -and $i -gt 0) {$mailD = ""}
if ($DelegateEmail.count -gt 1) {$MailD = $DelegateEmail.DelegateAddress[$i]}
$Result = [PSCustomObject]#{
PrimaryEmail = $SourceEmail
DelegateEmailAddress = $mailD
CalendarDelegateEmail = $DelegateCalendar.'scope.value'[$i]
CalendarRole = $DelegateCalendar.Role[$i]
CalendarDelegateType = $DelegateCalendar.'scope.type'[$i]
}
$Output += $Result
}
$Output | Export-Csv C:\test.csv -NoTypeInformation
I have data in a text file with the following columns.
Date
StringName
1/1/2021
ABC
2/1/2021
ABC
3/1/2021
ABC
1/1/2021
XYZ
2/1/2021
XYZ
3/1/2021
ABC
4/1/2021
ZZZ
I want only the StringName in the output which has consecutively failed for 3 days or more & ignore the rest. In the above data, ABC has failed for 1 2 3 days consecutively in Calendar month January. So the output should be ABC. If there are more than one stringName then the output should be like below
StringName
ABC
XYZ
Finally, I was able to achieve this. Thank you all
$file_data = get-content "c:\temp\txt.txt"
$dict_counter = #{}
$dict_dates = #{}
Foreach ($line in $file_data)
{
$values = $line.split(" ")
$pattern = '\d{4}-\d{2}-\d{2}'
[System.Text.RegularExpressions.Regex]$regex = New-Object System.Text.RegularExpressions.Regex($pattern)
[System.Text.RegularExpressions.Match]$m = $regex.Match($line)
if($m.Success)
{
$current_date = $m.Value
$sch_name = $values[7]
if($dict_dates.containsKey($sch_name))
{
$existing_date = $dict_dates.get_item($sch_name)
if($existing_date -ne $current_date)
{
$existing_date_format = [datetime]::parseexact($existing_date, 'yyyy-MM-dd', $null)
$current_date_format = [datetime]::parseexact($current_date, 'yyyy-MM-dd', $null)
$difference = (new-timespan -start $existing_date_format -end $current_date_format).days
if($dict_counter.containsKey($sch_name))
{
$diff = $dict_counter.get_item($sch_name)
$diff_new = [string]$diff + "," + [string]$difference
$dict_counter.set_item($sch_name, $diff_new)
}
else
{
$dict_counter.add($sch_name, $difference)
}
}
}
else
{
$dict_dates.add($sch_name, $current_date)
$dict_counter.add($sch_name, 0)
}
}
}
$fail_count = 0
$flagSequence = $false
$seqcounter = 0
Foreach ($value in $dict_counter.values)
{
if($value -ne 0)
{
$arr1 = $value.split(",")
$arr = foreach($number in $arr1){([int]::parse($number))}
$arr = $arr | sort
For($i = 1; $i -lt $arr.count; $i++)
{
$prev = $arr[$i - 1]
$curr = $arr[$i]
$dff = $curr - $prev
if(($dff -eq 1) -or ($dff -eq -1))
{
$flagSequence = $true
$seqcounter += 1
}
else
{
$flagSequence = $false
$seqcounter = 0
}
}
if($seqcounter -ge 2)
{
$fail_count += 1
}
}
}
$dict_counter
$fail_count
I am trying to compare two csv files, the first is called tickets.csv and contains the column headers: "tcn", "two", "twod". The second file is called tracker.csv and contains the headers: "cn", "wo", and "wod". I would like to output the contents of tracker.csv, and if any "tcn" (tickets.csv) match "cn" (tracker.csv), then write its associated "two" (tickets.csv) to "wo" (tracker.csv), and "twod" (tickets.csv) to "wod" (tracker.csv).
I'm running into the issue where my code isn't moving the "two" or "wod", and its also writing each object 4 times.
Input CSVs
Import-Csv "$home\Desktop\nestTest\tracker.csv" |
ForEach-Object {
$machine = $_.machine
$wo = ""
$wod = ""
$tickets = import-csv "$home\Desktop\nestTest\tickets.csv"
foreach ($ticket in $tickets) {
try {
$tcn = ""
$two = ""
$twod = ""
$two = $_.wo
$twod = $_.wod
$tcn = $_.cn
if ($tcn -eq $machine) {
$wo = $two
$wod = $twod
}
else {
$wo = ""
$wod = ""
}
}
catch {
}
[pscustomobject]#{
"Machine Name"=$machine
"Work Order #"=$wo
"Work Order Date"=$wod
}
}
} |
select "Machine Name","Work Order #","Work Order Date" |
Export-Csv "$home\Desktop\nestTest\output.csv"
I was looking in the wrong direction before. But I figured it out.
$tracker = Import-Csv "$home\Desktop\nestTest\tracker.csv" |
ForEach-Object {
$machine = ""
$wo = ""
$wod = ""
$machine = $_.machine
$tickets = import-csv "$home\Desktop\nestTest\tickets.csv" |
ForEach-Object {
$two = ""
$twod = ""
$two = $_."wo"
$twod = $_."wod"
$tcn = $_."cn"
if ($tcn -eq $machine) {
$wo = $two
$wod = $twod
}
else {
}
}
[pscustomobject]#{
"Machine Name"=$machine
"Work Order #"=$wo
"Work Order Date"=$wod
}
} |
select "Machine Name","Work Order #","Work Order Date" |
Export-Csv "$home\Desktop\nestTest\output.csv" -NoTypeInformation
I was asking myself how easily you could convert an Array of Numbers Like = 1,2,3,6,7,8,9,12,13,15 into 1 String that "Minimizes" the numbers, so Like = "1-3,6-9,12-13,15".
I am probably overthinking it because right now I don't know how I could achieve this easily.
My Attempt:
$newArray = ""
$array = 1,2,3,6,7,8,9,12,13,15
$before
Foreach($num in $array){
If(($num-1) -eq $before){
# Here Im probably overthinking it because I don't know how I should continue
}else{
$before = $num
$newArray += $num
}
}
This should working, Code is self explaining, hopefully:
$array = #( 1,2,3,6,7,8,9,12,13,15 )
$result = "$($array[0])"
$last = $array[0]
for( $i = 1; $i -lt $array.Length; $i++ ) {
$current = $array[$i]
if( $current -eq $last + 1 ) {
if( !$result.EndsWith('-') ) {
$result += '-'
}
}
elseif( $result.EndsWith('-') ) {
$result += "$last,$current"
}
else {
$result += ",$current"
}
$last = $current
}
if( $result.EndsWith('-') ) {
$result += "$last"
}
$result = $result.Trim(',')
$result = '"' + $result.Replace(',', '","') +'"'
$result
I have a slightly different approach, but was a little too slow to answer. Here it is:
$newArray = ""
$array = 1,2,3,6,7,8,9,12,13,15
$i = 0
while($i -lt $array.Length)
{
$first = $array[$i]
$last = $array[$i]
# while the next number is the successor increment last
while ($array[$i]+1 -eq $array[$i+1] -and ($i -lt $array.Length))
{
$last = $array[++$i]
}
# if only one in the interval, output that
if ($first -eq $last)
{
$newArray += $first
}
else
{
# else output first and last
$newArray += "$first-$last"
}
# don't add the final comma
if ($i -ne $array.Length-1)
{
$newArray += ","
}
$i++
}
$newArray
Here is another approach to the problem. Firstly, you can group elements by index into a hashtable, using index - element as the key. Secondly, you need to sort the dictionary by key then collect the range strings split by "-" in an array. Finally, you can simply join this array by "," and output the result.
$array = 1, 2, 3, 6, 7, 8, 9, 12, 13, 15
$ranges = #{ }
for ($i = 0; $i -lt $array.Length; $i++) {
$key = $i - $array[$i]
if (-not ($ranges.ContainsKey($key))) {
$ranges[$key] = #()
}
$ranges[$key] += $array[$i]
}
$sequences = #()
$ranges.GetEnumerator() | Sort-Object -Property Key -Descending | ForEach-Object {
$sequence = $_.Value
$start = $sequence[0]
if ($sequence.Length -gt 1) {
$end = $sequence[-1]
$sequences += "$start-$end"
}
else {
$sequences += $start
}
}
Write-Output ($sequences -join ",")
Output:
1-3,6-9,12-13,15