记录数据移至新行

记录数据移至新行

我有 CSV 文件,其中很少有记录的数据移动到新行:

例子:

  ABCD,1234,QWER
  ASDF
  ,2345,VGFT
  "ASDF,12",1212,ASDR 
  1234,ZXCV,ERTT

输出结果应该是:

  ABCD,1234,QWER
  ASDF,2345,VGFT
 "ASDF,12",1212,ASDR 
  1234,ZXCV,ERTT

有没有办法连接第二列和第三列?

答案1

这是一个天真的黑客,适用于给定的数据:

$ awk -F, 'NF != 3 { printf("%s",$0); getline } 1' file.csv
ABCD,1234,QWER
ASDF,2345,VGFT
1234,ZXCV,ERTT

它的作用是将awk文件解析为逗号分隔的数据集。如果一行不正好有三个字段 ( NF != 3),则按原样输出迄今为止已读取的行的位,不带尾随换行符,并读取下一行。 Final1是 的缩写{ print }并将打印所有行。

如果第一个块已触发,则最后的1/print将导致断线的其余部分在 输出的末尾输出printf

其变体为sed

$ sed -E '/^[^,]+,[^,]+,[^,]+$/!{ N; s/\n//; }' file.csv
ABCD,1234,QWER
ASDF,2345,VGFT
1234,ZXCV,ERTT

同样,如果线路以示例数据中所示的其他方式断开,则这可能不起作用。

sed脚本的作用是使用正则表达式测试每一行^[^,]+,[^,]+,[^,]+$。如果匹配,我们就有了一条看起来应该做的行;由逗号以外的字符组成的三个字段,以逗号分隔。如果那是不是在这种情况下,下一行将被附加到当前行的末尾,并且插入在两行之间的N换行符将被删除。sed

sed代码遵循与 代码相同的逻辑awk,如果当前行有故障,则它会追加下一行数据。

答案2

著名的sed一句台词的一种变体:

$ sed -e :a -e '$!N;s/\n[[:blank:]]*,/,/;ta' -e 'P;D' file.csv
  ABCD,1234,QWER
  ASDF,2345,VGFT
  "ASDF,12",1212,ASDR 
  1234,ZXCV,ERTT

答案3

通过混合 shell 变量,我们可以在 GNU 中执行此操作,sed如下所示:

nF='[^,]*';        # a normal unquoted csv field
qF='"[^"]*"';      # a quoted csv field
F="\($qF\|$nF\)";  # a csv field
ok="$F,$F,$F\$";   # a csv record with exactly 3 fields
# ok="\($F,\)\{2\}$F\$"; # an equivalent way to write out the regex for an ok csv record

sed -e "
    :a;/$ok/b       
    N;s/\n//;ba
" input.csv

输出

ABCD,1234,QWER
ASDF,2345,VGFT
"ASDF,12",1212,ASDR 
1234,ZXCV,ERTT

作为

  • 使用要在 sed 中使用的 shell 变量的混合来构建 csv 的语法。
  • 假设一条csv记录不超过3个字段。
  • 首先检查 csv 记录是否正常,也就是说,它正好有 3 个字段。在这种情况下,只需打印该记录并读取下一条记录即可。
  • OTW,意思是,在当前 csv 记录中找到的字段少于 3 个,我们通过命令附加下一行N,然后删除连接器 a \n,并使用此修改后的模式空间,分支到 sed 代码的顶部。

相关内容