【问题标题】:Calculate from specific CSV columns and output to a new file从特定的 CSV 列计算并输出到新文件
【发布时间】:2014-10-16 07:52:45
【问题描述】:

我正在尝试从一个 CSV 文件导入数据,对导入的数据进行一些计算,然后将其保存到一个新的 CSV 文件中,过去一天我一无所获。

总结:

我有一个带有数据列的管道分隔 CSV:

colA、colB、colC、colD、colE

colA 是字符串格式“20/01/2011 14:20:00”的日期时间 (dd/MM/yyyy HHmmss)

colC 是一个数字

我需要读取初始 CSV,然后从 colA 中的值,进行两个计算: 1 - 自 2000 年 1 月 1 日以来的天数和 2 - 从午夜开始的分钟数。

data.csv 中的示例数据:

01/01/2011 14:20:00|10|6|10|192.168.11.7|
01/01/2011 14:25:00|2|0|10|192.168.11.7|
01/01/2011 14:30:00|4|8|10|192.168.11.7|
01/01/2011 14:35:00|6|9|10|192.168.11.7|

然后我需要将计算的数据输出到一个新的 CSV 文件,该文件还添加了一些硬编码值/列(原始 dta,无标题):

(自 2000 年 1 月 1 日起的天数),(距午夜的分钟数),5,(colC 值),1,Text,A,0

** 括号中的值是从原始 CSV 计算/传递的。所有其他值都被硬编码到每个 CSV ROW 中。

所以对于上面的示例数据,新的输出将是(我再次为格式化目的添加了额外的换行符):

4018,860,5,6,1,Text,A,0
4018,865,5,0,1,Text,A,0
4018,870,5,8,1,Text,A,0
4018,875,5,9,1,Text,A,0

我可以将字段解析为这样的数组:

$data = Import-Csv c:\data.csv -Header colA, colB, colC, colD, colE -Delimiter '|' | Select-Object colA, colC
$newdata += $data
$newdata | convertto-csv -NoTypeInformation -Delimiter ',' | foreach-object {$_} | Out-File c:\newfile.csv

这将为我提供我所追求的两个字段,但我无法执行计算并在新的 CSV 中添加所需的额外硬编码字段。

在过去的一天里,我一直在谷歌上搜索并尝试了很多很多不同的方法,但我仍然一无所获。

任何人都可以提供一些帮助吗?谢谢。

【问题讨论】:

  • 请为输入和所需输出添加一些示例数据。
  • 示例数据添加到上面的主体。请原谅强制换行以保留格式。
  • 我为你修好了@gizmomelb。现在我可以用你的数据来试试我的答案

标签: powershell csv


【解决方案1】:

这样的事情应该让你开始

$path = "E:\temp\sample.csv"
$y2k = Get-Date -Date 1/1/2000
Import-Csv $path -Header colA, colB, colC, colD, colE -Delimiter '|' | ForEach-Object{
    $colADate = [datetime]::ParseExact($_.ColA,"dd/MM/yyyy HH:mm:ss",[System.Globalization.CultureInfo]::InvariantCulture)
    $minutesFromMidnight = $colADate.TimeOfDay.TotalMinutes
    $daysSincey2k = New-TimeSpan -Start $y2k -End $colADate | Select-Object -ExpandProperty Days
    [PSCustomObject][ordered]@{
        DaysSince = $daysSincey2k
        MinutesSince = $minutesFromMidnight
        ColA = $_.Cola
        ColB = $_.Colb
        ColC = $_.Colc
        ColD = $_.Cold
        ColE = $_.Cole
    }
}

您可以使用Select-Object 表达式将其设为单行,但这应该更易于阅读。您应该至少需要 PowerShell 3.0 才能工作。如果你没有它,这将只需要稍作调整。这是您的数据的输出

DaysSince MinutesSince ColA                ColB ColC ColD ColE        
--------- ------------ ----                ---- ---- ---- ----        
     4018          860 01/01/2011 14:20:00 10   6    10   192.168.11.7
     4018          865 01/01/2011 14:25:00 2    0    10   192.168.11.7
     4018          870 01/01/2011 14:30:00 4    8    10   192.168.11.7
     4018          875 01/01/2011 14:35:00 6    9    10   192.168.11.7

如果你的时间都是相同的格式,使用 ParseExact 方法会将其转换为 DateTime 对象。这使我们能够使用New-TimeSpan 确定时间差。使用计算字段创建自定义对象并添加计算数据。

评论更新

对于您正在寻找的静态输出,我将更改 [pscustomobject] 如下,并添加一个 export-csv 调用

    [PSCustomObject][ordered]@{
        DaysSince = $daysSincey2k
        MinutesSince = $minutesFromMidnight
        Five = 5
        ColC = $_.Colc
        One = 1
        Text = "Text"
        Bee = "B"
        Zero = 0
    }
} | Export-Csv -Path c:\newfile.csv -NoTypeInformation

对于 2.0,这应该可以工作

    $props = @{
        DaysSince = $daysSincey2k
        MinutesSince = $minutesFromMidnight
        Five = 5
        ColC = $_.Colc
        One = 1
        Text = "Text"
        Bee = "B"
        Zero = 0
    }

    New-Object PSObject -Property $props
} | Select-Object DaysSince,MinutesSince,Five,ColC,One,Text,Bee,Zero | Export-Csv -Path c:\temp\newfile.csv -NoTypeInformation

【讨论】:

  • 感谢您的建议/示例@Matt 如何将 Colc、DaysSince 和 MinutesSince 导出/保存到新文件?所以导出格式为:DaysSince,MinutesSince,5,ColC,1,Text,B,0 谢谢。
  • @gizmomelb 使用您的数据作为输入进行了更新。看看
  • 感谢@Matt - 其中一些对我来说甚至是有意义的,非常感谢您的帮助。但我想将 DaysSince、MinutesSince 和 colC 值保存到一个新的 CSV 文件中,该文件的每一行还添加了一些硬编码字段 - 请问我该如何处理?谢谢。
  • @gizmomelb 看看 bold 部分是否符合您的要求。
  • 谢谢你,谢谢你是一位优秀的老师——我只是在搜索,想问我是否需要使用 Export-CSV 命令。我没有意识到您可以对数组中的值进行硬编码,因为它被保存为 CSV 格式。再次感谢您的帮助和时间。
猜你喜欢
  • 2014-08-11
  • 2020-10-19
  • 2023-03-12
  • 2018-05-25
  • 2021-12-17
  • 2019-08-17
  • 2016-03-11
  • 1970-01-01
  • 2019-06-17
相关资源
最近更新 更多