比较两个 csv 表并同时写入其中一个

Posted

技术标签:

【中文标题】比较两个 csv 表并同时写入其中一个【英文标题】:Comparing two csv tables AND writing to one of them in the same time 【发布时间】:2021-09-02 13:52:05 【问题描述】:

我遇到了一个我无法解决的逻辑问题。

我想比较 2 个 csv 表,如果在 tableB 中没有找到 tableA 的值,脚本应该通过邮件通知我并将相应的值写入 tableB 以进行一次性通知。

表A:

ID Due_Date
2 26.09.2021 23:02:00
3 29.08.2021 03:52:00
4 10.11.2022 11:02:00
5 18.06.2021 02:48:00
6 09.03.2023 02:48:00
7 10.07.2021 02:48:00

TableB(最初为空):

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,而不仅仅是差异,而且每次运行都会增加行数。

我希望有人能帮我解决这个嵌套问题。

【问题讨论】:

【参考方案1】:

看起来没有任何理由对每一行执行操作,所以我建议改为:

$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 没有任何理由,因为您只会返回第一个 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.

【讨论】:

虽然我的回复来晚了,但我仍然要感谢您的 sn-p,它帮助我找到了解决方案。

以上是关于比较两个 csv 表并同时写入其中一个的主要内容,如果未能解决你的问题,请参考以下文章

sql数据库中的两个表的记录进行比较!并将结果写入表中!

如何使用 Python Pandas 比较两个不同大小的数据集?

如何对两个大型数据源 (csv) 进行比较

Python:比较两个excel表之间的列字符串并找到匹配的列并写入另一个数据框

使用hashmap或hashset比较大的csv文件

PowerShell - 从 csv 文件读取数据,比较特定列中的数据并将结果写入新文件