在字符串替换中使用正则表达式

时间:2016-12-10 23:04:10

标签: r regex csv replace

我有一个损坏的csv文件,我试图读入R并使用正则表达式进行修复。

它被破坏的原因是它包含一些包含逗号的字段,但不会用双引号将这些字段包装起来。所以我必须使用正则表达式来查找这些字段,并用双引号将它们包装起来。

以下是数据源的示例:

DataField1,DataField2,Price
ID1,Value1,
ID2,Value2,$500.00
ID3,Value3,$1,250.00

所以你可以看到,在第三行中,Price字段包含一个逗号,但它没有用双引号括起来。这打破了read.table函数。

我的方法是使用readLines和str_replace_all以逗号用双引号括起价格。但是我不擅长正则表达并且卡住了。

vector <- read.Lines(file)
vector_temp <- str_replace_all(vector, ",\\$[0-9]+,\\d{3}\\.\\d{2}", ",\"\\$[0-9]+,\\d{3}\\.\\d{2}\"")

我希望输出为:

DataField1,DataField2,Price
ID1,Value1,
ID2,Value2,$500.00
ID3,Value3,"$1,250.00"

使用这种格式,我可以阅读R. 感谢任何帮助!

3 个答案:

答案 0 :(得分:3)

lines <- readLines(textConnection(object="DataField1,DataField2,Price
ID1,Value1,
ID2,Value2,$500.00
ID3,Value3,$1,250.00"))

library(stringi)
library(tidyverse)

stri_split_regex(lines, ",", n=3, simplify=TRUE) %>% 
  as_data_frame() %>% 
  docxtractr::assign_colnames(1) 
##   DataField1 DataField2     Price
## 1        ID1     Value1          
## 2        ID2     Value2   $500.00
## 3        ID3     Value3 $1,250.00

您可以readr::write_csv()write.csv()

答案 1 :(得分:2)

似乎不需要stringi或stringr包中的额外工具。 gsub似乎非常适合这一点。您只需要了解带有成对括号的捕获组(括号到Brits)以及使用double-backslash_n约定来引用替换参数中的捕获组匹配:

txt <- "DataField1,DataField2,Price, extra
ID1,Value1, , 
ID2,Value2,$500.00,
ID3,Value3,$1,250.00, o"

vector<- gsub("([$][0-9]{1,3}([,]([0-9]{3})){0,10}([.][0-9]{0,2}))" , "\"\\1\"", readLines(textConnection(txt)) )

> read.csv(text=vector)
  DataField1 DataField2     Price extra
1        ID1     Value1                
2        ID2     Value2   $500.00      
3        ID3     Value3 $1,250.00     o

您可以在可能重复的特定数字序列(逗号数字)和可能的句点和2位数字周围加上引号。可能有更早的关于格式化为“货币”的问题。

答案 2 :(得分:2)

以下是一些解决方案:

1)read.pattern 这使用gsubfn包中的read.pattern读取文件(假设称为sc.csv),以便捕获组,即模式的括号部分是字段。这将读入文件并一步完成所有操作,因此不必先使用readLines

开始模式的

^(.*?),将匹配从开始到第一个逗号的所有内容。然后(.*?),将与下一个逗号匹配,最后(.*)$将匹配其他所有内容。通常*是贪婪的,即它尽可能匹配,但是它之后的问号使它不合适。我们需要指定perl=TRUE以便它使用perl正则表达式,因为默认情况下gsubfn使用基于Henry Spencer的正则表达式解析器的tcl正则表达式,它不支持*?。如果您希望使用字符列而不是因子,请将as.is=TRUE参数添加到read.pattern

最后一行代码会从价格列中删除$,字符,并将其转换为数字。 (如果您确实想要格式化,请省略此行。)

library(gsubfn)

DF <- read.pattern("sc.csv", pattern = "^(.*?),(.*?),(.*)$", perl = TRUE, header = TRUE)
DF$Price <- as.numeric(gsub("[$,]", "", DF$Price)) ##

,并提供:

> DF
 DataField1 DataField2 Price
1        ID1     Value1    NA
2        ID2     Value2   500
3        ID3     Value3  1250

2)sub 这使用非常简单的正则表达式(只是一个字符匹配)而没有包。使用问题中定义的vector,将前两个逗号替换为分号。然后可以使用sep = ";"

读取它
read.table(text = sub(",", ";", sub(",", ";", vector)), header = TRUE, sep = ";")

如果您想要数字价格,请在(1)中添加标记为##的行。