比较两个 csv 表并同时写入其中一个
Comparing two csv tables AND writing to one of them in the same time
我遇到了一个无法解决的逻辑问题。
我想比较 2 个 csv 表,如果表 A 中的值在表 B 中找不到,脚本应该通过邮件通知我并将相应的值写入表 B 以进行一次性通知。
表A:
ID
Due_Date
2
26.09.2021 23:02:00
3
29.08.2021 03:52:00
4
2022 年 11 月 10 日 11:02:00
5
18.06.2021 02:48:00
6
2023 年 3 月 9 日 02:48:00
7
10.07.2021 02:48:00
表 B(最初为空):
ID
2
3
4
如果我第一次 运行 脚本,它应该会看到 TableB 不包含来自 TableA 的任何或所有数据,因此将它们写入 TableB。
如果我再次 运行 脚本,脚本应该注意到 TableB 现在包含 TableA 拥有的所有数据,因此不会向其写入任何内容,因为目前没有区别(例如,可能会在 1 天后更改,当新条目将添加到 TableA 时)。
我遇到了问题,当我第二次执行脚本时,TableA 中的数据仍然会添加到 TableB 中,尽管它们已经存在于其中。我需要此功能让脚本在“日期”数据之前 x 天向我发送电子邮件并且只发送一次,即使脚本将在另一次执行。我的代码的主要部分在这里:
$CheckDate = Get-Date -f 'dd.MM.yyyy HH:mm' #get current date and reformat it, to compare later
$TableA = Import-Csv -Path $TableA_path -Delimiter ";" #import tableA
$TableB = Import-Csv -Path $TableB_path -Delimiter ";" #import tableB (can be empty yet or not)
foreach ($row in $TableA) {
$due_Date = $row.date #Put the tabledate in a variable
$Time_Difference = (New-Timespan -Start $CheckDate -End $due_Date).Days
If (($Time_Difference -ge 0) -and ($Time_Difference -le 30)) { #if due date is 30 days or less from now
:outer
foreach ($id in $TableB) {
if($id.id -ne $row.id){ #if the id from TableB is NOT in TableA
$row.id + ";" |Add-Content -Path $TableB #Add entry from TableA to TableB
$msg.subject = "Due date for id $id.id is close!" #Set Mail Subject
$msg.body = "Please take a look" #Set Mail Body
$smtp.Send($msg) #Send Mail
break :outer #break loop
}
else{
Write-Host("Everything fine")
}
}
}
}
我的脚本不仅将 TableA 中的所有数据再次写入 TableB 而不仅仅是差异,而且还将行数乘以每个 运行。
我希望有人能帮我解决这个嵌套问题。
看起来没有任何理由对每一行执行一个操作,所以我建议改为:
$TableA = Import-Csv -Path $TableA_path |
Select *,@{l='Date';e={[datetime]$_.Due_Date}}
$TableB = Import-Csv -Path $TableB_path
$Now = Get-Date
# if due date is 30 days or less from now
$Due_Soon = $TableA | Where {
($_.date -gt $Now) -and
($_.date -lt $Now.AddDays(30))
}
# and not in tableB
$Adding = $Due_Soon | Where {$_.ID -Notin $TableB.ID}
# Add to tableB
$Adding | Export-Csv $TableB_path -Append
# And create notification
$msg.subject = "Due date(s) for id(s) $($Due_Soon.ID) soon!"
在您的脚本中,我看不出有任何理由 break
,因为您只会 return 第一个 ID。您还希望更好地跟踪比较了哪些行:
# simplified:
foreach ($A in $TableA) {
foreach ($B in $TableB) {
if ($B.id -ne $A.id) {
Add A to B
# Here you were adding A if ANY row in B did NOT match.
}}}
我遇到了一个无法解决的逻辑问题。
我想比较 2 个 csv 表,如果表 A 中的值在表 B 中找不到,脚本应该通过邮件通知我并将相应的值写入表 B 以进行一次性通知。
表A:
ID | Due_Date |
---|---|
2 | 26.09.2021 23:02:00 |
3 | 29.08.2021 03:52:00 |
4 | 2022 年 11 月 10 日 11:02:00 |
5 | 18.06.2021 02:48:00 |
6 | 2023 年 3 月 9 日 02:48:00 |
7 | 10.07.2021 02:48:00 |
表 B(最初为空):
ID |
---|
2 |
3 |
4 |
如果我第一次 运行 脚本,它应该会看到 TableB 不包含来自 TableA 的任何或所有数据,因此将它们写入 TableB。 如果我再次 运行 脚本,脚本应该注意到 TableB 现在包含 TableA 拥有的所有数据,因此不会向其写入任何内容,因为目前没有区别(例如,可能会在 1 天后更改,当新条目将添加到 TableA 时)。
我遇到了问题,当我第二次执行脚本时,TableA 中的数据仍然会添加到 TableB 中,尽管它们已经存在于其中。我需要此功能让脚本在“日期”数据之前 x 天向我发送电子邮件并且只发送一次,即使脚本将在另一次执行。我的代码的主要部分在这里:
$CheckDate = Get-Date -f 'dd.MM.yyyy HH:mm' #get current date and reformat it, to compare later
$TableA = Import-Csv -Path $TableA_path -Delimiter ";" #import tableA
$TableB = Import-Csv -Path $TableB_path -Delimiter ";" #import tableB (can be empty yet or not)
foreach ($row in $TableA) {
$due_Date = $row.date #Put the tabledate in a variable
$Time_Difference = (New-Timespan -Start $CheckDate -End $due_Date).Days
If (($Time_Difference -ge 0) -and ($Time_Difference -le 30)) { #if due date is 30 days or less from now
:outer
foreach ($id in $TableB) {
if($id.id -ne $row.id){ #if the id from TableB is NOT in TableA
$row.id + ";" |Add-Content -Path $TableB #Add entry from TableA to TableB
$msg.subject = "Due date for id $id.id is close!" #Set Mail Subject
$msg.body = "Please take a look" #Set Mail Body
$smtp.Send($msg) #Send Mail
break :outer #break loop
}
else{
Write-Host("Everything fine")
}
}
}
}
我的脚本不仅将 TableA 中的所有数据再次写入 TableB 而不仅仅是差异,而且还将行数乘以每个 运行。
我希望有人能帮我解决这个嵌套问题。
看起来没有任何理由对每一行执行一个操作,所以我建议改为:
$TableA = Import-Csv -Path $TableA_path |
Select *,@{l='Date';e={[datetime]$_.Due_Date}}
$TableB = Import-Csv -Path $TableB_path
$Now = Get-Date
# if due date is 30 days or less from now
$Due_Soon = $TableA | Where {
($_.date -gt $Now) -and
($_.date -lt $Now.AddDays(30))
}
# and not in tableB
$Adding = $Due_Soon | Where {$_.ID -Notin $TableB.ID}
# Add to tableB
$Adding | Export-Csv $TableB_path -Append
# And create notification
$msg.subject = "Due date(s) for id(s) $($Due_Soon.ID) soon!"
在您的脚本中,我看不出有任何理由 break
,因为您只会 return 第一个 ID。您还希望更好地跟踪比较了哪些行:
# simplified:
foreach ($A in $TableA) {
foreach ($B in $TableB) {
if ($B.id -ne $A.id) {
Add A to B
# Here you were adding A if ANY row in B did NOT match.
}}}