替换CSV第一列中的数据

时间:2014-12-17 21:06:14

标签: powershell

我有一个包含许多列的CSV,第一列中的数据是日期,但格式错误。我只能选择第一列并重新格式化日期,但我无法弄清楚如何将新数据保存到现有CSV而不会覆盖所有其他数据。

$File = "File.csv"
$Content = Get-Content $File
$timestamp = @()
$timestamp += '"' + "timestamp" + '"'
$timestamp += $Content | Foreach { $_.Split(",") | select -first 1 } | select -skip 1 -last 10000 | where {$_ -notmatch "timestamp"} | foreach {($_).Substring(1,$_.Length-2)} | foreach {get-date ($_).ToString() -Format s} | foreach {'"' + $_ + '"'}

在:

"timestamp"
"17-Dec-2014 07:00:00 AM"
"17-Dec-2014 07:15:00 AM"
"17-Dec-2014 07:30:00 AM"
"17-Dec-2014 07:45:00 AM"
"17-Dec-2014 08:00:00 AM"

后:

"timestamp"
"2014-12-17T07:00:00"
"2014-12-17T07:15:00"
"2014-12-17T07:30:00"
"2014-12-17T07:45:00"
"2014-12-17T08:00:00"

2 个答案:

答案 0 :(得分:2)

在文件c:\temp\test.csv

中考虑csv格式的以下数据
old_timestamp   timestamp
12/17/2014 7:00 12/17/2014 7:00
12/17/2014 7:15 12/17/2014 7:15
12/17/2014 7:30 12/17/2014 7:30
12/17/2014 7:45 12/17/2014 7:45
12/17/2014 8:00 12/17/2014 8:00

我会做这样的事情。操作old_timestamp“列”并将更改输出回管道。

Import-CSV C:\temp\test.csv | ForEach-Object{
    $_.old_timestamp = get-date $_.old_timestamp -Format s
    $_
}

示例输出:

old_timestamp       timestamp      
-------------       ---------      
2014-12-17T07:00:00 12/17/2014 7:00
2014-12-17T07:15:00 12/17/2014 7:15
2014-12-17T07:30:00 12/17/2014 7:30
2014-12-17T07:45:00 12/17/2014 7:45
2014-12-17T08:00:00 12/17/2014 8:00

现在你可以随心所欲地做它,就像输出回文件一样!

Import-CSV C:\temp\test.csv | ForEach-Object{
    $_.old_timestamp = get-date $_.old_timestamp -Format s
    $_
} | Export-Csv C:\temp\updated_test.csv -NoTypeInformation

Simlar方法

您可以使用可以执行相同操作的Select-Object语句

Import-CSV C:\temp\test.csv | 
    Select-Object @{Name="New_TimeStamp";Expression = {get-date $_.old_timestamp -Format s}},* -ExcludeProperty old_timestamp

这仅在列名不同时才有效。它将通过指定New_TimeStamp将格式化的列输出为*以及其余数据。从我所看到的你的其他问题来看,这可能不会与他们融洽,但这是一个解决方案。

答案 1 :(得分:2)

使用System.DateTime类的ParseExact()方法将字符串输入解析为日期,并通过ToString()方法将日期转换回格式化字符串。

$csv = 'C:\path\to\your.csv'

$culture = [Globalization.CultureInfo]::InvariantCulture
$srcfmt  = 'dd-MMM-yyyy hh:mm:ss tt'
$dstfmt  = 'yyyy-MM-ddTHH:mm:ss'

(Import-Csv $csv) | % {
  $date = [DateTime]::ParseExact($_.timestamp, $srcfmt, $culture)
  $_.timestamp = $date.ToString($dstfmt)
  $_      # required to inject the current object back into the pipeline
} | Export-Csv $csv -NoType

您可以将其替换为calculated property,而不是使用循环来更新timestamp属性:

$csv = 'C:\path\to\your.csv'

$culture = [Globalization.CultureInfo]::InvariantCulture
$srcfmt  = 'dd-MMM-yyyy hh:mm:ss tt'
$dstfmt  = 'yyyy-MM-ddTHH:mm:ss'

(Import-Csv $csv) |
  select @{n='timestamp';e={
    [DateTime]::ParseExact($_.timestamp, $srcfmt, $culture).ToString($dstfmt)
  }}, other, properties, here, ...  |
  Export-Csv $csv -NoType

请注意,必须在子表达式中运行Import-Csv(或首先在变量中捕获其输出),否则文件仍会在{{1开始写它。