Powershell 替换CSV第一列中的数据
我有一个有很多列的CSV,第一列中的数据是日期,但格式错误。我可以只选择第一列并重新格式化日期,但我不知道如何在不覆盖所有其他数据的情况下将新数据保存到现有CSVPowershell 替换CSV第一列中的数据,powershell,Powershell,我有一个有很多列的CSV,第一列中的数据是日期,但格式错误。我可以只选择第一列并重新格式化日期,但我不知道如何在不覆盖所有其他数据的情况下将新数据保存到现有CSV $File = "File.csv" $Content = Get-Content $File $timestamp = @() $timestamp += '"' + "timestamp" + '"' $timestamp += $Content | Foreach { $_.Split(",") | select -first
$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"
考虑文件c:\temp\test.csv中csv格式的以下数据 我会这样做。操作旧的_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对象语句,它可以做同样的事情
Import-CSV C:\temp\test.csv |
Select-Object @{Name="New_TimeStamp";Expression = {get-date $_.old_timestamp -Format s}},* -ExcludeProperty old_timestamp
这仅在列名不同时才起作用。它将格式化列作为新的_时间戳输出,并通过指定*输出其余数据。从我看到的你的其他问题来看,这可能与他们不太合拍,但这是一个解决办法 使用System.DateTime类的方法将字符串输入解析为日期,并通过其ToString方法将日期转换回格式化字符串
$csv='C:\path\to\your.csv'
$culture=[Globalization.CultureInfo]::不变量文化
$srcfmt='dd-MMM-yyyy-hh:mm:ss-tt'
$dstfmt='yyyy-MM-ddTHH:MM:ss'
导入Csv$Csv |%{
$date=[DateTime]::ParseExact$\时间戳,$srcfmt,$culture
$\时间戳=$date.ToString$dstfmt
$\将当前对象注入回管道需要
}|导出Csv$Csv-NoType
除了使用循环来更新timestamp属性外,还可以将其替换为:
$csv='C:\path\to\your.csv'
$culture=[Globalization.CultureInfo]::不变量文化
$srcfmt='dd-MMM-yyyy-hh:mm:ss-tt'
$dstfmt='yyyy-MM-ddTHH:MM:ss'
导入Csv$Csv|
选择@{n='timestamp';e={
[日期时间]::ParseExact$\时间戳,$srcfmt,$culture.ToString$dstfmt
}},其他,属性,此处|
导出Csv$Csv-NoType
请注意,无论哪种方式,您都必须先在子表达式中运行Import Csv或在变量中捕获其输出,因为否则当Export Csv开始写入文件时,文件仍将被打开读取。只要OPs real data中显示的时间与他问题中的时间相同,是否真的需要使用ParseExact?使用OP中的Get-Date-Format s似乎工作得很好?@Matt ParseExact在这种特殊情况下可能不需要,但它是更通用的方法。Get Date只能处理ParseExact可以处理的格式的子集。这确实可以更新CSV,但它重复了最后一行并添加了另一行,我收到以下错误:使用3个参数调用ParseExact时出现异常:字符串未被识别为有效的日期时间。CSV后面有一个空行。修复CSV或添加筛选器以从处理中排除该行:导入CSV$CSV |?{$\.timestamp}{…}当我不运行Export Csv并且数据被输出到屏幕时,这会起作用。但是当我使用Export Csv运行它时,文件是空白的。
Import-CSV C:\temp\test.csv |
Select-Object @{Name="New_TimeStamp";Expression = {get-date $_.old_timestamp -Format s}},* -ExcludeProperty old_timestamp