【问题标题】:removing new line characters in csv file from inside columns in unix从 unix 的列中删除 csv 文件中的换行符
【发布时间】:2021-10-25 10:00:36
【问题描述】:

样本输入数据::

cat test.csv
234,aa,bb,cc,30,dd

22,cc,

ff,dd,

40,gg

pxy,aa,,cc,

40

,dd

需要的输出::

cat test_new.csv
234,aa,bb,cc,30,dd

22,cc,ff,dd,40,gg

pxy,aa,,cc,40,dd

我尝试了各种awksed 命令,似乎没有任何效果。

例如:: awk 'NR == 1{ printf $0; next } { printf "%s%s", (/^[0-9]+,/? ORS : ""), $0 } END{ print "" }'

awk 上方仅查找带有 "," 的数字字符,但如果数字出现在带有换行符的列中,这将创建额外的行。

输入文件包含 Control M 字符,我已经使用 dos2unix 删除了这些字符

【问题讨论】:

  • 您好,我在 csv 文件的列之间添加了换行符。有没有办法在 unix CSV 文件中删除列内的换行符。试过这个 AWK 命令 awk 'NR == 1{ printf $0; next } { printf "%s%s", (/^[0-9]+,/? ORS : ""), $0 } END{ print "" }' ,这工作 99 % 好,但不能处理数字进入文件,列之间有换行符,并为相同创建一个新行
  • 那么,您基本上只想用逗号替换每个序列 吗?你考虑过sed吗?
  • 它不仅仅是用逗号替换逗号和换行符,它就像替换两个逗号内的换行符一样。这也不应该影响行格式。这将读取一个内部包含 CLOB 列的 CSV 文件,并且在这些 CLOB 列中,我们需要处理换行符
  • 但这不是和我说的一样吗?替换 comma-newline 等效于删除逗号后面的那些换行符,至少对于您的输入,这将提供您所请求的输出。
  • 我提供了一个示例数据,但在实际数据中,我们可能不会一直有逗号与换行符。把它当作第二或第三列是excel中的一个clob列,我们有一个段落,其中有很多没有逗号的换行符。当我们以 csv 格式读取此文件时。它显示一行分成 8-10 行

标签: shell csv unix awk newline


【解决方案1】:

关于“输入文件包含 Control M 字符,我已经使用 dos2unix 删除了” - 这可能会让您的生活更加艰难。一行中的“换行符”很有可能只是LFs,而记录结尾是CRLF,因此通过删除CRs,我们不能再简单地将awk RS 设置为@987654326 @ 然后删除记录中剩余的任何LFs。

如果您的文件是按照您在问题下的 cmets 中所说的那样从 Excel 导出的,那么无论字段是否被引用,它都会在每条记录的末尾使用 CRLF,并在每条记录中单独使用 LF如果你不在上面运行dos2unix,看起来像这样的字段:

$ cat -v test.csv
234,aa,bb,cc,30,dd^M
22,cc,
ff,dd,
40,gg^M
pxy,aa,,cc,
40
,dd^M

然后使用任何 awk:

$ awk -v ORS= '{sub(/\r$/,"\n")} 1' test.csv
234,aa,bb,cc,30,dd
22,cc,ff,dd,40,gg
pxy,aa,,cc,40,dd

或者,如果您愿意,可以将 GNU awk 用于多字符 RS:

$ awk -v RS='\r\n' '{gsub(/\n/,"")} 1' test.csv
234,aa,bb,cc,30,dd
22,cc,ff,dd,40,gg
pxy,aa,,cc,40,dd

有关使用 awk 解析 CSV 的更多信息,请参阅What's the most robust way to efficiently parse CSV using awk?

关于您的原始脚本 - 永远不要使用 printf $0,始终使用 printf "%s", $0,因为当 $0 包含任何 printf 格式字符(例如 %s)时前者会失败:

$ echo 'a%sb' | awk '{printf "%s", $0}'
a%sb$

$ echo 'a%sb' | awk '{printf $0}'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: not enough arguments to satisfy format string
        `a%sb'
          ^ ran out for this one
$

这适用于对所有输入数据使用printf

【讨论】:

  • 感谢 Ed 提供的信息,这对我有用 awk -v ORS= '{sub(/\r$/,"\n")} 1'
  • 想知道,如果同一个输入文件中没有控制 M 字符,同样的命令可以正常工作吗?
  • 不客气。不,它专门使用控制 Ms(又名 CR 又名 \rs)将出现在记录(CRLF)末尾的 LFs(又名 \ns)与出现在记录中间的那些( LF 单独)。如果您没有CRs,那么您需要一个完全不同的解决方案,该解决方案要么依赖于仅出现在引用字段中的LFs,要么提前知道每行应该存在多少个字段。
  • 在不同的文件上尝试了相同的 awk 命令,在文件列和文件开头之间有 '"' 和 '-'。不知何故,那里的数据没有正确排序
  • 抱歉,我不知道这意味着什么,提出一个新问题并将这些案例包含在示例输入/输出中。
猜你喜欢
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
相关资源
最近更新 更多