【问题标题】:Is this the best way to replace text in all of an object's properties in powershell?这是在powershell中替换所有对象属性中的文本的最佳方法吗?
【发布时间】:2017-05-29 14:01:34
【问题描述】:

我有一个大型 CSV 文件,其中一些字段嵌入了新行。 Excel 2016 在导入包含嵌入新行的字段的行的 CSV 时会产生错误。

基于this post,我编写了代码以用空格替换任何字段中的任何新行。下面是一个复制功能和问题的代码块。选项 1 有效。被注释掉的选项 2 将我的对象转换为字符串。我希望选项 2 可以运行得更快。

问题:有没有更好的方法来优化处理超大文件的性能?

$array = @([PSCustomObject]@{"ID"="1"; "Name"="Joe`nSmith"},
           [PSCustomObject]@{"ID"="2"; "Name"="Jasmine Baker"})

$array = $array | ForEach-Object {
    #Option 1: produces an Object, but is code optimized?
    foreach ($n in $_.PSObject.Properties.Name) {
        $_.PSObject.Properties[$n].Value = ` 
             $_.PSObject.Properties[$n].Value -replace "`n"," "
    }

    #Option 2: produces a string, not an object
    #$_ = $_ -replace "`n"," " 

    $_
 }

请记住,在我的实际用例中,每一行都有 > 15 个字段,并且它们的任意组合都可能嵌入一个或多个新行。

【问题讨论】:

  • 我在某处读到 ForEach 比 ForEach-Object 快。您可以对您在秒表类中提到的两种情况进行一些测试。像这样使用它: $resultstime = new-timespan -Minutes 1 $resultstime = [diagnostics.stopwatch]::StartNew() $resultstime.Elapsed 记得停止它:)
  • 谢谢马丁。我将使用秒表类并将我的原始代码与@wOxxOm 的建议进行比较。
  • 请分享你的发现:)
  • 使用我大约 16.5 MB 和 25,000 行的数据集,ForEach-Object 循环在 36 秒内运行。 foreach 循环在 11 中运行。

标签: powershell replace newline


【解决方案1】:
  • 使用快速TextFieldParser 从文件中读取、处理和构建 CSV(PowerShell 3+):

    [Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') >$null
    $parser = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser 'r:\1.csv'
    $parser.SetDelimiters(',')
    $header = $parser.ReadFields()
    
    $CSV = while (!$parser.EndOfData) {
        $i = 0
        $row = [ordered]@{}
        foreach ($field in $parser.ReadFields()) {
            $row[$header[$i++]] = $field.replace("`n", ' ')
        }
        [PSCustomObject]$row
    }
    
  • 或者在已经存在的 CSV 数组中就地修改每个字段:

    foreach ($row in $CSV) {
        foreach ($field in $row.PSObject.Properties) {
            $field.value = $field.value.replace("`n", ' ')
        }
    }
    

注意事项:

  1. foreach statement 比管道到ForEach-Object(也别名为foreach)快得多
  2. $stringVariable.replace()-replace 更快

【讨论】:

  • 感谢您的详细回复。我会尝试这两种方法,看看哪种方法更快。
  • foreach 绝对比 Foreach-Object 快。替换循环使用 ForEach-Object 需要 36 秒,而使用 foreach 循环只需 11 秒。
  • 我也放弃了尝试在对象上使用 -replace。它似乎只是将结果变成一个字符串。对于每周两次的脚本来说,11 秒已经足够快了。
  • 只是为了链接问题,我为另一个问题写了一个 similar answer,我将 TextFieldParser 包装在一个可重用的函数中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
相关资源
最近更新 更多