使用Regex清理R中的csv文件

时间:2015-10-02 15:27:03

标签: regex r csv data-cleaning

这是我的第一篇文章,所以我希望它足够清楚。 我有一个关于清理我的CSV文件的问题,然后才能将它们读入R并且花了一整天的时间来寻找解决方案。

我的数据应该是两列的形式。第一列是由10位数组成的时间戳,第二列是由11或12个字母和数字组成的ID(前6个始终是数字)。

例如:

logger10    |
0821164100  |   010300033ADD
0821164523  |   010300033ADD
0821164531  |   010700EDDA0F0831102744
010700EDDA0F|

会变成:

0821164100  |   010300033ADD
0821164523  |   010300033ADD
0821164531  |   010700EDDA0F
0831102744  |   010700EDDA0F

(请原谅中间的线条,这是我试图分隔列......)。

csv文件似乎偶尔会丢失一个逗号,这意味着有时候一行最终会像这样结束:

0923120531,010300033ADD0925075301,010700EDD00A

我的硬件每次重新启动时都会添加单词logger10(或者这个数字记录器),这会产生类似的问题,例如: logger10logger100831102744

我想我已经设法解决了记录器文本问题(参见代码),但我确信这可以改进。另外,我真的不想删除任何数据。 我真正的麻烦是确保在ID之后的正确位置有换行符,如果没有,我想添加一个换行符。我以为我可以使用正则表达式,但我很难理解它。

非常感谢任何帮助!

这是我的尝试:

temp <- list.files(pattern="*.CSV") #list of each csv/logger file
for(i in temp){

    #clean each csv
    tmp<-readLines(i) #check each line in file

    tmp<-gsub("logger([0-9]{2})","",tmp) #remove logger text
    pattern <- ("[0-9]{10}\\,[0-9]{6}[A-Z,0-9]{5,6}") #regex pattern ??
    if (tmp!= pattern){ 
        #I have no idea where to start here... 
    }
}

这里有一些原始数据: logger01 0729131218,020700EE1961 0729131226,020700EE1961 0831103159,0203000316DB 0831103207,0203000316DB0831103253,010700EDE28C 0831103301,010700EDE28C 0831103522,010300029815 0831103636,010300029815 0831103657,020300029815

2 个答案:

答案 0 :(得分:1)

如果您想一次性完成此操作:

(?:logger\d\d )?([\dA-F]{10}),?([\dA-F]{12}) ?

可以替换为

\1\t\2\n

这样做是为了寻找任何那些流氓logger01条目(包括它后面的空格)可选:在组之后尾随?意味着它可以匹配0或1次:如果它 匹配,它会。如果不存在,那么比赛就会继续进行。

然后,您会查找(并捕获)10个十六进制值(数字或A-F)。 ,?表示如果逗号存在,它将匹配,但它也可以匹配0或1次(使其成为可选项)。

然后,查找(并捕获)正好12个十六进制值。最后,为了摆脱任何奇怪的尾随空格,?(后跟?的空格字符)将可选地匹配尾随空格。

您的替换将替换第一个捕获的组(10个十六进制数字),添加选项卡,替换第二个捕获的组(12个十六进制数字),然后换行。

您可以在regex101上看到此消息,以查看结果。您可以使用该页面左侧的code generator来获取一些预先格式化的PHP / Javascript / Python,您可以将其放入脚本中。

如果您从命令行执行此操作,可以使用perl:

perl -pe 's/(?:logger\d\d )?([\dA-F]{10}),?([\dA-F]{12}) ?/\1\t\2\n/g'

如果使用其他语言,您可能需要稍微调整一下以满足您的需求。

修改

重新阅读OP和评论,一个稍微僵硬的正则表达式可能

(?:logger\d\d\ )?([\dA-F]{10}),?(\d{6}[\dA-F]{5,6})\ ?

我使用更改更新了regex101链接。

这仍然会查找前10个十六进制值,但现在查找正好6位数,然后是5-6个十六进制值,因此匹配的字符总数为11或12。

替换将是相同的。

答案 1 :(得分:0)

将您的正则表达式粘贴到https://regex101.com/以查看它是否捕获了所有情况。 5或6个字母或数字可能会造成问题,因为它可能会在记录器错过逗号时捕获时间戳的第一个数字。如果正则表达式捕获所有情况,则应在tmp字符串的末尾附加'\ n'。