使用 PowerShell 限制 csv 列长度
Limit csv column length using PowerShell
我正在尝试使用 PowerShell 调整 tab-delimited 文本文件 而没有 headers 并将输出写入相同的 tab-delimited文本文件。目前源数据如下;
- AAA\t BBBBBB\t CCCCCCCCCCC
- AAAA\t BBBB\t AAAABBBBCCCCCCC
现在第三列应仅限于前 5 个字符,使输出如下所示;
- AAA\t BBBBBB\t CCCCC
- AAAA\t BBBB\t AAAAB
我怎样才能做到这一点?
导入后截断:
Import-Csv ... | ForEach-Object { if ($_.Column3.Length -gt 5) { $_.Column3.Substring(0, 5) }; $_ }
如果您希望将规则应用于所有属性,您可以创建通用 属性 循环,而不是按名称定位特定 属性。
Import-Csv ... | ForEach-Object {
foreach ($property in $_.PSObject.Properties) {
if ($property.Value.Length -gt 5) {
$property.Value = $property.Value.Substring(0, 5)
}
}
$_
}
Import-Csv 本身不会为您做这些,这不是它接受培训的工作。
可以将自己的header信息传递给Import-Csv
:
# Import the file with the proper delimiter and dummy headings
(Import-Csv foo.tsv -delim "`t" -header c1,c2,c3) |
# Truncate the third column accordingly. Regex because I'm lazy.
ForEach-Object { $_.c3 = $_.c3 -replace '(?<=^.{5}).*'; $_ } |
# Convert back to TSV. This also emits the headers
ConvertTo-Csv -NoTypeInformation -delim "`t" |
# Remove the headers again
Select -Skip 1 |
# Write back to file
Out-File foo.tsv -Encoding UTF8
以下代码将使用 Import-Csv
导入 CSV 文件,然后遍历所有行,在将行写入新的 CSV 文件之前创建第 3 列的子字符串(长度为 5)。
$oldCSV = "T:\OLD.csv"
$newCSV = "T:\New.csv"
Import-Csv -Delimiter "`t" -Path $oldCSV -Header "1","2","3" | ForEach-Object {
"{0}`t{1}`t{2}" -f $_.1,$_.2,($_.3).Substring(0,[Math]::Min(5,($_.3).Length)) >> $newCSV
}
更好的模块化方法是将修改后的对象通过管道传输到 Export-Csv
commandlet。
$charLimit=100
Import-Csv "$_" -Delimiter "`t" | ForEach-Object {
$_."column 1" = $_."column 1".Substring(0,[Math]::Min($charLimit,($_.'column 1').Length))
$_."column 2" = $_."column 2".Substring(0,[Math]::Min($charLimit,($_.'column 2').Length))
Write-Output $_
} | Export-Csv $targetfile -NoTypeInformation
在上面的代码片段中 Write-Output
会将修改后的对象向下传递到管道。这将比修改时写入更快,因为 Export-Csv 将比这更好地处理文件输出。
我正在尝试使用 PowerShell 调整 tab-delimited 文本文件 而没有 headers 并将输出写入相同的 tab-delimited文本文件。目前源数据如下;
- AAA\t BBBBBB\t CCCCCCCCCCC
- AAAA\t BBBB\t AAAABBBBCCCCCCC
现在第三列应仅限于前 5 个字符,使输出如下所示;
- AAA\t BBBBBB\t CCCCC
- AAAA\t BBBB\t AAAAB
我怎样才能做到这一点?
导入后截断:
Import-Csv ... | ForEach-Object { if ($_.Column3.Length -gt 5) { $_.Column3.Substring(0, 5) }; $_ }
如果您希望将规则应用于所有属性,您可以创建通用 属性 循环,而不是按名称定位特定 属性。
Import-Csv ... | ForEach-Object {
foreach ($property in $_.PSObject.Properties) {
if ($property.Value.Length -gt 5) {
$property.Value = $property.Value.Substring(0, 5)
}
}
$_
}
Import-Csv 本身不会为您做这些,这不是它接受培训的工作。
可以将自己的header信息传递给Import-Csv
:
# Import the file with the proper delimiter and dummy headings
(Import-Csv foo.tsv -delim "`t" -header c1,c2,c3) |
# Truncate the third column accordingly. Regex because I'm lazy.
ForEach-Object { $_.c3 = $_.c3 -replace '(?<=^.{5}).*'; $_ } |
# Convert back to TSV. This also emits the headers
ConvertTo-Csv -NoTypeInformation -delim "`t" |
# Remove the headers again
Select -Skip 1 |
# Write back to file
Out-File foo.tsv -Encoding UTF8
以下代码将使用 Import-Csv
导入 CSV 文件,然后遍历所有行,在将行写入新的 CSV 文件之前创建第 3 列的子字符串(长度为 5)。
$oldCSV = "T:\OLD.csv"
$newCSV = "T:\New.csv"
Import-Csv -Delimiter "`t" -Path $oldCSV -Header "1","2","3" | ForEach-Object {
"{0}`t{1}`t{2}" -f $_.1,$_.2,($_.3).Substring(0,[Math]::Min(5,($_.3).Length)) >> $newCSV
}
更好的模块化方法是将修改后的对象通过管道传输到 Export-Csv
commandlet。
$charLimit=100
Import-Csv "$_" -Delimiter "`t" | ForEach-Object {
$_."column 1" = $_."column 1".Substring(0,[Math]::Min($charLimit,($_.'column 1').Length))
$_."column 2" = $_."column 2".Substring(0,[Math]::Min($charLimit,($_.'column 2').Length))
Write-Output $_
} | Export-Csv $targetfile -NoTypeInformation
在上面的代码片段中 Write-Output
会将修改后的对象向下传递到管道。这将比修改时写入更快,因为 Export-Csv 将比这更好地处理文件输出。