什么';使用awk高效解析CSV最可靠的方法是什么?

什么';使用awk高效解析CSV最可靠的方法是什么?,csv,awk,Csv,Awk,这个问题的目的是提供一个规范的答案 给定一个可能由Excel或其他工具生成的CSV,其中包含嵌入的换行符、嵌入的双引号和空字段,如: $ cat file.csv "rec1, fld1",,"rec1"",""fld3.1 "", fld3.2","rec1 fld4" "rec2, fld1.1 fld1.2","rec2 fld2.1&qu

这个问题的目的是提供一个规范的答案

给定一个可能由Excel或其他工具生成的CSV,其中包含嵌入的换行符、嵌入的双引号和空字段,如:

$ cat file.csv
"rec1, fld1",,"rec1"",""fld3.1
"",
fld3.2","rec1
fld4"
"rec2, fld1.1

fld1.2","rec2 fld2.1""fld2.2""fld2.3","",rec2 fld4
使用awk有效识别单独记录和字段的最可靠方法是什么:

Record 1:
    $1=<rec1, fld1>
    $2=<>
    $3=<rec1","fld3.1
",
fld3.2>
    $4=<rec1
fld4>
----
Record 2:
    $1=<rec2, fld1.1

fld1.2>
    $2=<rec2 fld2.1"fld2.2"fld2.3>
    $3=<>
    $4=<rec2 fld4>
----
记录1:
$1=
$2=

$3=如果您的CSV不能包含换行符或转义双引号,那么您所需要的就是(GNU awk用于):

$echo'foo,“字段,带逗号”,条形”|

awk-v FPAT='[^,]*|“[^”]+''{for(i=1;i如果您的CSV不能包含换行符或转义双引号,那么您所需要的就是(使用GNU awk for):

$echo'foo,“字段,带逗号”,条形”|

awk-v FPAT='[^,]*|“[^”]+'''{for(i=1;i是对@EdMorton的
FPAT
解决方案的改进,该解决方案应该能够处理通过加倍(
”)转义的双引号(
),这是CSV允许的

这仍然

  • 无法处理引用字段中的换行符,这在标准CSV文件中是完全合法的

  • 假设gnuawk
    gawk
    ),标准的awk就不行了

  • 例如:

    $ echo 'a,,"","y""ck","""x,y,z"," ",12' |
    gawk -v OFS='|' -v FPAT='[^,]*|("[^"]*")+' '{$1=$1}1'
    a||""|"y""ck"|"""x,y,z"|" "|12
    
    $ echo 'a,,"","y""ck","""x,y,z"," ",12' |
    gawk -v FPAT='[^,]*|("[^"]*")+' '{
      for(i=1; i<=NF;i++){
        if($i~/"/){ $i = substr($i, 2, length($i)-2); gsub(/""/,"\"", $i) }
        print "<"$i">"
      }
    }'
    <a>
    <>
    <>
    <y"ck>
    <"x,y,z>
    < >
    <12>
    
    $echo'a,,,,,“y”“ck”“x,y,z”“12”|
    gawk-vofs='|'-vfpat='[^,]*|(“[^”]*”)+“{$1=$1}1”
    a | y | ck | x,y,z | 12
    $echo'a,,,,,“y”“ck”,“x,y,z”,“12”|
    gawk-v FPAT='[^,]*|(“[^”]*''”+“”{
    
    对于(i=1;i对@EdMorton的
    FPAT
    解决方案的改进,该解决方案应该能够处理通过加倍(
    ”)转义的双引号(
    ——CSV允许)

    这仍然

  • 无法处理引用字段中的换行符,这在标准CSV文件中是完全合法的

  • 假设gnuawk
    gawk
    ),标准的awk就不行了

  • 例如:

    $ echo 'a,,"","y""ck","""x,y,z"," ",12' |
    gawk -v OFS='|' -v FPAT='[^,]*|("[^"]*")+' '{$1=$1}1'
    a||""|"y""ck"|"""x,y,z"|" "|12
    
    $ echo 'a,,"","y""ck","""x,y,z"," ",12' |
    gawk -v FPAT='[^,]*|("[^"]*")+' '{
      for(i=1; i<=NF;i++){
        if($i~/"/){ $i = substr($i, 2, length($i)-2); gsub(/""/,"\"", $i) }
        print "<"$i">"
      }
    }'
    <a>
    <>
    <>
    <y"ck>
    <"x,y,z>
    < >
    <12>
    
    $echo'a,,,,,“y”“ck”“x,y,z”“12”|
    gawk-vofs='|'-vfpat='[^,]*|(“[^”]*”)+“{$1=$1}1”
    a | y | ck | x,y,z | 12
    $echo'a,,,,,“y”“ck”,“x,y,z”,“12”|
    gawk-v FPAT='[^,]*|(“[^”]*''”+“”{
    
    对于(i=1;我也看到了这是一个很好的FPAT,我无法想象它会允许任何无效的情况-你应该建议gawk People更新使用它,而不是
    FPAT=“([^,]*)|”(\“[^\”]+\”)
    如该部分底部所述,我使用了。这是一个很好的FPAT,我无法想象它会允许任何无效的情况-你应该建议gawk人员更新使用它,而不是
    FPAT=“([^,]*)|”(\“[^\”]+\”
    如该部分底部所述,我使用过。
    $ awk -f decsv.awk file.csv
    Record 1:
        $1=<rec1, fld1>
        $2=<>
        $3=<rec1","fld3.1
    ",
    fld3.2>
        $4=<rec1
    fld4>
    ----
    Record 2:
        $1=<rec2, fld1.1
    
    fld1.2>
        $2=<rec2 fld2.1"fld2.2"fld2.3>
        $3=<>
        $4=<rec2 fld4>
    ----
    
    gawk -v FPAT='[^,]*|("[^"]*")+' ...
    
    $ echo 'a,,"","y""ck","""x,y,z"," ",12' |
    gawk -v OFS='|' -v FPAT='[^,]*|("[^"]*")+' '{$1=$1}1'
    a||""|"y""ck"|"""x,y,z"|" "|12
    
    $ echo 'a,,"","y""ck","""x,y,z"," ",12' |
    gawk -v FPAT='[^,]*|("[^"]*")+' '{
      for(i=1; i<=NF;i++){
        if($i~/"/){ $i = substr($i, 2, length($i)-2); gsub(/""/,"\"", $i) }
        print "<"$i">"
      }
    }'
    <a>
    <>
    <>
    <y"ck>
    <"x,y,z>
    < >
    <12>