【问题标题】:Sort and export-CSV排序和导出-CSV
【发布时间】:2016-08-24 02:45:35
【问题描述】:

我有一个包含以下提取行的 csv 文件:

“员工 ID”、“名字”、“姓氏”、“位置”、“部门”、“电话号码”、“电子邮件”
"000001 ","abc ","def ","Loc1"," "," ","name1@company.com "
"000023 ","ghi ","jkl ","Loc2"," "," ","name2@company.com "
"000089","mno","pqr","Loc2","","","name3@company.com"

如何保留引号并排序并保存为 csv 文件?

我有以下 powershell 源脚本,它适用于列没有双引号的 csv 文件:

Get-Content $Source -ReadCount 1000 |
    ConvertFrom-Csv -Delimiter $Delimiter | 
    Sort-Object -Property $NamesOfColumns -Unique |
    ForEach-Object {
        # Each of the values in $ColumnValueFormat must be executed to get the property from the loop variable ($_). 
        $values = foreach ($value in $ColumnValueFormat) {
            Invoke-Expression $value
        }
        # Then the values can be passed in as an argument for the format operator.
        $ShowColsByNumber -f $values
    } | 
    Add-Content $Destination;

$Source$Delimiter$NamesOfColumns$ColumnValueFormat 是动态给出或构建的。

$ColumnValueFormat 带有未引用的 csv 文件包含:

$_.EmployeeID.Trim()
$_.FirstName.Trim()
$_.LastName.Trim()
$_.Location.Trim()
$_.Department.Trim()
$_.TelephoneNo.Trim()
$_.Email.Trim()

$ColumnValueFormat 带引号的 csv 文件包含:

$_."EmployeeID".Trim()
$_."FirstName".Trim()
$_."LastName".Trim()
$_."Location".Trim()
$_."Department".Trim()
$_."TelephoneNo".Trim()
$_."Email".Trim()

问题似乎是基于 $ColumnValueFormat 将列标题放在双引号中。 (如果我删除它们,我不确定 cmdlet 的内部是否会在处理行时识别列标题)

我有两个问题:

  1. 用双引号括起来的列标题。问题似乎是基于$ColumnValueFormat 将列标题放在双引号中,因为它不处理行。 (如果我删除双引号,那么它在处理行时无法识别列标题)。
  2. 我在最后一分钟遇到的另一个问题是,如果最后一列是空白的,它会认为它是一个空值,并且当 Invoke-Expression $value 执行时(其中$value 包含 $_.Email.Trim() 的最后一列表达式 - 在未引用的 CSV 文件上) 它会爆炸。如果我尝试将语句放在 try/catch 块中,它只会忽略它,最后一列不会添加到 $values 数组中并再次炸弹。

【问题讨论】:

  • 你想用你的脚本实现什么?
  • 感谢您的回复。只需处理 CSV 文件,无论 CSV 文件的列是否有双引号,以及最后一列是否包含空白,因为它看到一个回车以允许包含 $_.Email.Trim( ) 表达式来执行,因此它可以在 $values 数组中放置一个额外的元素,该数组包含一个空白(由 ForEach 循环的完成分配)。

标签: powershell


【解决方案1】:

属性名称周围的引号在语法上用于访问带有空格的名称,而不是在输出中写入引号。

Export-Csv cmdlet 没有强制使用引号的选项,因此我们必须手动导出 CSV。我们将不得不处理$NullConvertFrom-Csv 之后的空值和一个空字符串。如果只需要一些字段,我们将使用 Select cmdlet 和 -index 参数。

Get-Content $Source |
    ConvertFrom-Csv |
    %{ $header = $false } {
        if (!$header) {
            $header = $true
            '"' + (
                ($csv[0].PSObject.Properties.Name.trim() |
                    select -index 1,6
                ) -join '","'
            ) + '"'
        }
        '"' + (
            ($_.PSObject.Properties.Value |
                %{ if ($_) { $_.trim() } else { '' } } |
                select -index 1,6
            ) -join '","'
        ) + '"'
    } | Out-File $Destination

上述代码非常适合大型 CSV 文件的直通处理,因为它不会将整个文件保存在内存中。否则可以稍微简化一下代码:

$csv = Get-Content $Source | ConvertFrom-Csv
$csv | %{
    '"' + (
        ($csv[0].PSObject.Properties.Name.trim() |
            select -index 1,6
        ) -join '","'
    ) + '"'
} {
    '"' + (
        ($_.PSObject.Properties.Value |
            %{ if ($_) { $_.trim() } else { '' } } |
            select -index 1,6
        ) -join '","'
    ) + '"'
) | Out-File $Destination

【讨论】:

  • 感谢您的回复。将类似地更改我的代码并让您知道。 :-)
  • 还有一件事你会如何让它充满活力。因此,您可以选择要转到输出文件的列吗?在我的原始代码中,我将 $ShowColsByNumber 作为 {2},{4}。所以我可以得到我想要的列到输出文件。
  • 通常的数组选择工作:'"' + (($_.PSObject.Properties.Value.trim() | select -index 1,3) -join '","') + '"'
  • 好的。伟大的。会尝试并让你知道。谢谢您的帮助。 :-)
  • 效果很好!只有障碍,如果最后一列是空白的(在最后一个逗号后有空格和 CR/NL 或 CR/NL),它会爆炸:08/23/2016 09:21:44 - - 错误:您不能在 null- 上调用方法有价值的表达。在 C:\windows\system32\windowspowershell\v1.0\Modules\FileUtilities\FileUtilities.psm1:6421 char:11 + ... '"' + ($_.PSObject.Properties.Value.trim() -join ' ","') + ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : InvokeMethodOnNull
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-30
  • 1970-01-01
  • 2022-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多