【问题标题】:How to do math operation for multiple csv files如何对多个csv文件进行数学运算
【发布时间】:2020-03-04 20:20:23
【问题描述】:

我找到了这段代码:

$csv = Import-Csv D:\ExcelFiles\ba.csv
$csvout = "D:\ExcelFiles\bas.csv"

$csv | ForEach-Object {
    # Do the math
    $_.result = [math]::round($_.A / $_.B, 0)
    # Output the object (which contains A, B and result)
    $_
} | Export-Csv $csvout -NoTypeInformation

如您所见,它仅适用于导入的 csv 文件。多csv文件怎么做这个操作?

编辑1:

我已经使用了这个代码:

$SourcePath = "D:\CsvFiles"

$CsvFiles = Get-ChildItem -Path $SourcePath -filter "*.csv"

foreach ($File in $CsvFiles)
{
 $OutFile = "D:\CsvFiles\" + "\" + $File.BaseName + "s" + $File.Extension

$File | ForEach-Object 
{

            $_.result = [math]::round($_.A / $_.B, 0)
            # Output the object (which contains A, B and result)
            $_
        } | Export-Csv $OutFile -NoTypeInformation
}

但它要求:

cmdlet ForEach-Object at command pipeline position 1

Supply values for the following parameters:

为了防止这种情况,我更改了如下代码(foreach 对象后的括号位置):

$SourcePath = "D:\CsvFiles"

$CsvFiles = Get-ChildItem -Path $SourcePath -filter "*.csv"

foreach ($File in $CsvFiles)
{
 $OutFile = "D:\CsvFiles\" + "\" + $File.BaseName + "s" + $File.Extension

$File | ForEach-Object {

            $_.result = [math]::round($_.A / B, 0)
            # Output the object (which contains A, B and result)
            $_
        } | Export-Csv $OutFile -NoTypeInformation
}

这一次,我得到了这个错误:

在此对象上找不到属性“结果”。验证该属性是否存在并且可以设置。

谢谢。

【问题讨论】:

  • 所有的csv文件都在同一个目录下吗?你试过什么?您是否考虑将上述内容包装在另一个 foreach 循环中?
  • 请注意,这是“银行家的四舍五入”。奇数向上取整,事件数向下取整。

标签: powershell csv


【解决方案1】:

首先,Get-ChildItem 返回 FileInfo 和/或 DirectoryInfo 对象,因此我建议将-File 开关添加到它,这样您就知道您只是在处理文件。

然后,你遍历这些文件,在那个循环中你正在做一些非常奇怪的事情,即$File | ForEach-Object。此处的变量 $File 包含单个 FileInfo 对象,而不是该文件的导入数据

该问题并未说明是否所有文件实际上都有一个名为 result 的列,因此代码应检查这一点,最后,请记住从 CSV 导入的任何内容都是一个字符串。要对其进行数学运算,您需要转换为数字数据类型。 下面的代码为此使用了一个简单的转换为[double]

$SourcePath = "D:\CsvFiles"
$CsvFiles   = Get-ChildItem -Path $SourcePath -Filter "*.csv" -File

$CsvFiles | ForEach-Object {
    # create an output filepath. Since you are filtering on '*.csv', we can hardcode the extension here
    $OutFile = Join-Path -Path $SourcePath -ChildPath ('{0}s.csv' -f $_.BaseName)

    # so you know what file you are creating
    Write-Host "Working on $OutFile" -ForegroundColor Yellow

    # import the data from the file ($_) and calculate
    Import-Csv -Path $_.FullName | ForEach-Object {
        # since you're doing math, the values in A and B need to be converted from string to numeric type
        $result = [Math]::Round([double]$_.A / [double]$_.B, 0)
        # if the csv does not contain a column 'result', create it
        if ($_.PSObject.Properties.Name -notcontains 'result') { 
            $_ | Add-Member -MemberType NoteProperty -Name 'result' -Value $result 
        }
        else {
            $_.result = $result
        }
        # Output the object (which contains A, B and result)
        $_
    } | Export-Csv -Path $OutFile -NoTypeInformation
}

【讨论】:

    【解决方案2】:

    假设所有文件都在同一个目录下,上面的其余部分正是如你所愿:

    $Directory = "D:\CSVFiles"
    
    $Files = Get-ChildItem -Path $Directory
    
    foreach ($File in $Files)
    {
        $OutFile = $Directory + "\" + $File.BaseName + "s" + $File.Extension
    
        $File | ForEach-Object
            {
                $_.result = [math]::round($_.A / $_.B, 0)
                # Output the object (which contains A, B and result)
                $_
            } | Export-Csv $OutFile -NoTypeInformation
    }
    

    当然,没有示例文件,这是无法测试的。

    【讨论】:

    • 您好,感谢您的回复。我试过你的代码,但它要求参数。我编辑并更新了我的问题。
    • @echelon 我假设您拥有的其余代码是正确的(正如我在回答中所述)。如果您已经拥有的代码不起作用,那是一个有点不同的问题。我只向您展示了如何对目录中的每个文件使用它。
    猜你喜欢
    • 2013-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 2015-12-01
    • 2021-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多