首页 > 解决方案 > PowerShell:条件 CSV 单元格值

问题描述

在 table.csv 中已经有名为 Enrolled 和 Status 的列。还有其他列,但它们不相关。

已注册 地位
2021 年 7 月 28 日 13:37 未知
2021 年 7 月 21 日 13:37 未知
2021 年 7 月 14 日 13:37 未知

如果注册日期距今天不到 1 周,则状态单元格将更改为 PAST DUE

如果从今天开始注册日期大于 1 周前,它将变为 DISABLE

如果注册日期从今天起超过 2 周前,它将变为 DISABLED STILL PAST DUE

最终结果应该将 table.csv 更改为如下所示:

已注册 地位
2021 年 7 月 28 日 13:37 逾期
2021 年 7 月 21 日 13:37 禁用
2021 年 7 月 14 日 13:37 禁用仍然过期
$csv = Import-Csv file.csv
$pastdue = (Get-Date).AddDays(-7)
foreach($i in $csv.Enrolled){
    if ($i -lt $pastdue){
        ???
    }
}

我在想 switch 函数可能有用,但不知道如何实现它。

标签: powershellcsv

解决方案


是的,使用switch语句是一种选择。

您可以将其与Select-Object计算属性结合使用:

$oneWeekAgo = (Get-Date).Date.AddDays(-7)
$twoWeeksAgo = (Get-Date).Date.AddDays(-14)

$csv | Select-Object Enrolled, @{ 
         Name = 'Status'
         Expression = {
          switch ([datetime] $_.Enrolled) {
            { $_ -lt $twoWeeksAgo } { 'DISABLED STILL PAST DUE'; break }
            { $_ -lt $oneWeekAgo }  { 'DISABLE'; break }
            default                 { 'PAST DUE' }
          } 
         }
       }

上面将结果对象输出到显示器,以表格形式(仅)显示Enrolled和列,如您的问题所示。Status


为了更新原始 CSV 文件,同时仅更新Status列并保持所有其他列不变,请使用以下命令:

  • 为了安全起见,请先备份file.csv
  • Import-Csv请注意 ) 中的调用的附件(...,它确保预先完整读取它,从而可以在同一管道中更新同一文件;如果文件太大而无法放入内存,请删除(...), 输出到临时文件,然后用临时文件替换原始文件。
  • 您可能必须-Encoding在调用中添加一个参数Export-Csv,因为后者的默认编码是在其他情况下应用的,即 Windows PowerShell 中的 ASCII(!),更明智的是 PowerShell (Core) 7+ 中的无 BOM UTF-8。
$oneWeekAgo = (Get-Date).Date.AddDays(-7)
$twoWeeksAgo = (Get-Date).Date.AddDays(-14)

(Import-Csv file.csv) | ForEach-Object {

  # Update the .Status property.
  $_.Status = switch ([datetime] $_.Enrolled) {
            { $_ -lt $twoWeeksAgo } { 'DISABLED STILL PAST DUE'; break }
            { $_ -lt $oneWeekAgo }  { 'DISABLE'; break }
            default                 { 'PAST DUE' }
          } 

  # Output the modified object.
  $_

} | Export-Csv -NoTypeInformation file.csv

推荐阅读