从 CSV 文件的列中删除换行符

从 CSV 文件的列中删除换行符

我们在 CSV 文件的一列中获取换行符。该列的数据位于连续的行中。例如:

ID,CODE,MESSAGE,DATE,TYPE,OPER,CO_ID
12202,INT_SYS_OCS_EX_INT-0000,"""OCSSystemException: HTTP transport error: java.net.ConnectException: Tried all: '1' addresses, but could not connect over HTTP to server: '10.244.166.9', port: '8080'
 failed reasons:
  [0] address:'/10.244.166.9',port:'8080' : java.net.ConctException: Connection refused
""",06-09-2021 05:52:32,error,BillCycle,6eb8642aa4b
20840,,,06-09-2021 16:17:18,response,changeLimit,1010f9ea05ff

问题在于列Message和 id 12202 ,其中数据采用三引号且位于连续行中。

我的要求是,对于列Message,数据应该出现在单行而不是多行中,因为我的 etl 加载器无法导入嵌入的换行符。

答案1

如果您的 CSV 是由 Excel 等 MS 工具生成的,则字段中间的“换行符”只是 LF,而每条记录末尾的“换行符”是 CRLF,如下所示(请注意 LF$中字段与^M$记录末尾的CRLF ):

$ cat -Ev file
ID,Code,Message,date^M$
1244,,"""Exception error : java connection error$
:8080 Connection refused""",01-09-2021^M$

如果是这样,您可以告诉 GNU awk(对于多字符 RS)记录以 CRLF 结尾,并用空格替换中间记录 LF:

$ awk -v RS='\r\n' '{gsub(/\n/," ")} 1' file
ID,Code,Message,date
1244,,"""Exception error : java connection error :8080 Connection refused""",01-09-2021

如果您只有 POSIX awk 并且没有适用于 CSV 的工具,请参阅使用 awk 有效解析 csv 的最稳健方法是什么要了解如何处理它们,或者如果 CR 没有出现在文件中的其他位置,您可以使用任何 awk 执行此操作:

$ awk -v RS='\r' 'NR>1{print prev} {sub(/^\n/,""); gsub(/\n/," "); prev=$0}' file
ID,Code,Message,date
1244,,"""Exception error : java connection error :8080 Connection refused""",01-09-2021

答案2

一种简单的方法是删除只有 3 个字段的行上的换行符:

$ perl -F','  -pane 's/\n// if $#F==2' file 
ID,Code,Message,date
1244,,"""Exception error : java connection error:8080 Connection refused""",01-09-2021
1245,,"""Exception error :""",01-09-2021
1246,,"ffadsdasd",01-09-2021

当然,这是假设您永远不能拥有,内部字段,而 CSV 文件中允许这样做。因此,如果您的Message字段包含类似的内容"""foo,bar""",它可能会失败。这就是为什么使用专用解析器总是更好的原因。

此方法适用于任何有效的 CSV 文件:

$ perl -MText::CSV -le '$csv = Text::CSV->new({binary=>1}); while ($row = $csv->getline(STDIN)){ $row->[2]=~s/\n//; $csv->print(STDOUT,$row)}' < file
ID,Code,Message,date
1244,,"""Exception error : java connection error:8080 Connection refused""",01-09-2021
1245,,"""Exception error :""",01-09-2021
1246,,ffadsdasd,01-09-2021

答案3

如果您有csvkit实用程序,则可以修复带有嵌入换行符的行,例如通过将换行符转换为文字两个字符\n

csvformat -M $'\r' datafile |                    # temporarily end lines with $'\r'
    sed -e ':a' -e 'N;$!ba' -e 's/\n/\\n/g' |    # transform $'\n' into '\n'
    tr '\r' '\n'                                 # convert the line endings back to $'\n'

感谢 csvkit github 上的海报他们的解决方案,这又链接回一个答案在 StackOverflow 上

答案4

第一步运行 CSV 文件并转换为 Unix 行结尾:

dos2unix your_csvfile

在下一步中这将更改为\r\n“然后”:\n

使用 GNU sed 我们跟踪双引号的偶数/奇数,如下所示:

sed -Ee '
  h;s/[^"]*//g
  /^(..)*$/!{
    z;G;N;D
  }
  g;s/\n//g
' your_csvfile

perl -pe 's/\n/<>/e while y/"// % 2' your_csvfile

我们可以使用 awk 实用程序来计算双引号的数量并不断累积行,直到它们变为偶数。

awk '{
  t = $0
  while ((gsub(/"/,"&",t) ~ /[13579]$/) && (getline nxt > 0)) 
    t = t nxt
  print t
}' your_csvfile

输出:

     1  ID,Code,Message,date$
     2  1244,,"""Exception error : java connection error:8080 Connection refused""",01-09-2021$

相关内容