如何检测并删除 csv 文件列中的换行符?

如何检测并删除 csv 文件列中的换行符?

csv我有一个从数据库导出的大文件(200 万行)SQL Server。我无权访问数据库,并且列中存在一些换行符,这使得在R.

示例数据如下:

playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0
,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060
,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9

在上面的示例数据中,有些行分成两行。如何清理它?

更新

  1. csv文件是在Microsoft平台上生成的。所以行结尾是^m.我在 Linux 上编写了示例数据 - 以\n.是我不好,没说清楚。但我想我可以用\n来代替\r\n
  2. 换行符并不总是出现在逗号之前,即使在像这样的字段中,它也会随机出现

Bill 
Gates.

解决了

步骤1:^M从线的中间删除:

perl -pe 's/\r(?!\n)//g'

参考:https://stackoverflow.com/questions/6081465/how-to-remove-carriage-returns-in-the-middle-of-a-line

第2步:替换\n,,(参见下面@jimmij的回答。)

perl -p00e 's/\n,/,/g' 

答案1

我们以此作为测试文件:

$ cat file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0
,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060
,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9
Bill
Gates,1933,0,ALS193307060,NYA,AL,1,9

这会将各行重新组合在一起:

$ awk 'NR==1{printf "%s",$0; gsub(/[^,]/,""); nlast=n=length($0); next;} nlast==n{printf "\n";nlast=0} {printf "%s",$0; gsub(/[^,]/,""); nlast+=length($0)} END{print ""}' file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9
BillGates,1933,0,ALS193307060,NYA,AL,1,9

我不清楚行结束要求。我们可以在这里添加代码来处理它。或者,为了获得最大的灵活性,您可以根据需要运行该dos2unix文件unix2dos

回答问题的第一个版本

我有一个大(200 万行)的 csv 文件

这是一种面向行的解决方案,不需要立即将整个文件读入内存:

$ awk 'NR>1 && !/^,/{printf "\n";} {printf "%s",$0} END{print ""}' file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9

怎么运行的

  • NR>1 && !/^,/{printf "\n";}

    如果我们不在第一行 ,NR>1并且当前行不以逗号 开头,!/^,/则打印换行符。

  • {printf "%s",$0}

    打印当前行,不带换行符。

  • END{print ""}

    当我们到达文件末尾时,再打印一个换行符来终止最后一行。

答案2

perl救援:

$ perl -p00e 's/\n,/,/g' file
playerID,yearID,gameNum,gameID,teamID,lgID,GP,startingPos
gomezle01,1933,0,ALS193307060,NYA,AL,1,1
ferreri01,1933,0,ALS193307060,BOS,AL,1,2
gehrilo01,1933,0,ALS193307060,NYA,AL,1,3
gehrich01,1933,0,ALS193307060,DET,AL,1,4
dykesji01,1933,0,ALS193307060,CHA,AL,1,5
cronijo01,1933,0,ALS193307060,WS1,AL,1,6
chapmbe01,1933,0,ALS193307060,NYA,AL,1,7
simmoal01,1933,0,ALS193307060,CHA,AL,1,8
ruthba01,1933,0,ALS193307060,NYA,AL,1,9

我在这里假设,分割总是在逗号之前,

相关内容