gpt4 book ai didi

正则表达式拆分csv,值被引号包围,值有引号

转载 作者:行者123 更新时间:2023-12-01 00:17:30 26 4
gpt4 key购买 nike

我不太擅长正则表达式,我的任务是使用 powershell 将 csv 加载到数据表中。 csv 的值用引号括起来,用逗号分隔。问题是,某些行由列值组成,在值本身中包含引号。

$csvSplit = "($csvdelimiter)"
$csvSplit += '(?=(?:[^"]|"[^"]*")*$)'
$regexOptions = [System.Text.RegularExpressions.RegexOptions]::ExplicitCapture
抛出它的行在其中包含值,其中值可能表示类似 3-1/8" 的内容。作为值(value)的一部分。我也是 powershell 的菜鸟,但我真的不知道如何更改正则表达式以忽略这些类型的情况。
非常感谢任何解释和帮助!
更新
尝试这些解决方案似乎并没有全心全意地解决问题,只是将问题移到了不同​​的地方。我相信问题出在 CSV 本身,但我找不到格式错误的例子。这些答案很棒,我希望将来有人会从阅读这篇文章及其出色的答案中有所收获。谢谢大家。

最佳答案

因为"字符。嵌入在您的字段中不会被转义:

  • 您无法可靠地使用 Import-Csv (或 ConvertFrom-Csv)。
  • 用于现场内部 "字符。要正确解析,它们必须表示为 "" (翻倍)。
  • 需要手动解析工作,这仅在您做出假设时才有效。

  • 如果可以假设嵌入式(field-interior) "永远不会直接跟随 , ,您可以尝试以下方法(PSv4+):
    # Sample array of CSV lines.
    # Note that some fields have unescaped internal " chars.
    $csv = @'
    "col1","col2"
    "one","3-1/0""
    "normal","line"
    "3-1/1"","two"
    "3" of rain","today"
    '@ -split '\r?\n'


    $lineNo = 0
    # Process the CSV lines one by one.
    # Note: Replace `$csv |` with `Get-Content yourFile.csv`
    $csv | ForEach-Object {
    # Extract the field values based on the assumption above.
    $fieldValues = ([regex]::Matches($_, '"(.*?)"(?:,|$)')).ForEach({ $_.Groups[1].Value })
    if (++$lineNo -eq 1) { # 1st == header line
    # Create an object *template* with the 1st line's field values as
    # property names.
    $propNames = $fieldValues
    $ohtAux = [ordered] @{}
    foreach ($propName in $propNames) { $ohtAux[$propName] = $null }
    $objTemplate = [pscustomobject] $ohtAux
    } else { # 2nd and subsequent lines: data lines
    # Clone the template object.
    $obj = $objTemplate.psobject.Copy()
    # Fill the clone's properties with the field values.
    $i = 0
    foreach ($propName in $propNames) { $obj.$propName = $fieldValues[$i++] }
    # Output the clone.
    $obj
    }
    }

    以上产生:

    col1       col2
    ---- ----
    one 3-1/0"
    normal line
    3-1/1" two
    3" of rain today

    警告:鉴于必须为每个输入行执行一个脚本块,此解决方案将相对较慢。

    笔记:
  • 正则表达式 '"(.*?)"(?:,|$)'非贪婪*?匹配 " -封闭值只要收盘"要么紧跟一个 ,或 ( | ) 行尾 ( $ )。
  • .*?(...) - 捕获组 - 在 " 之间生成字符串实例(即原始字段值)可用作 1 的第二个元素(索引 .Groups ) [regex]::Matches() 返回的匹配对象的属性
  • 请注意 ?:(?:,|$)表示非捕获组,选择该组是因为稍后不需要访问组匹配的内容。除了稍后指示哪些组感兴趣之外,这还使正则表达式稍微更有效。
  • 注:wp78de's helpful answer展示了一种基于使用正则表达式匹配分隔符而不是字段值的更简单、更快速的方法,它直接返回原始字段值。
  • .ForEach({ $_.Groups[1].Value })因此输出所有原始字段值并将它们保存为变量 $fieldValues 中的数组.
  • $ohtAux = [ordered] @{}foreach ($propName in $propNames) { $ohtAux[$propName] = $null }定义一个带有有序键的辅助哈希表,并为第一个输入行的字段值创建(最初为空)条目,这些值被假定为列名; [pscustomobject] $ohtAux然后将哈希表转换为自定义对象,该对象用作对象的模板,以便为要遵循的数据行输出。
  • 关于正则表达式拆分csv,值被引号包围,值有引号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51236528/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com