分割部分引用、逗号分隔的字符串

问题描述 投票:0回答:1

在 R 中,我在

data.frame
列中有一些格式相当不寻常的字符串,我想用逗号分隔它们(即,该列的每个元素都是用逗号分隔的单个值的字符串;这些字符串来自
postgresql 
查询,但问题更普遍,由于各种原因我无法修复这是
postgresql
查询本身)。包含字符串的数据框
x
如下所示:

> x
                                     v
1                              {'a',b}
2 {"abc, def","the \\"big\\" one",fgh}

注意:上面引用内容中的双斜杠

\\
只是转义实际字符串中的单个
\

如果值本身包含空格、双引号或逗号,则用逗号分隔的值列表中的任何元素都会加上双引号,但如果值不使用这些特殊字符,则不使用双引号。单个值中的文字双引号表示为文字

\"
。这些特征使得用逗号分割值非常困难。

我想拆分这些值,使

{'a',b}
变为
c("'a'","b")
{"abc, def","the \\"big\\" one",fgh}
变为
c("abc, def","the \"big\" one","fgh")
。我已经找到了解决这个问题的办法,但它是“丑陋”的大写U,我想知道是否有更好的方法。我的解决方案是: # Code to create data.frame using postgresql query con <- DBI::dbConnect(RPostgres::Postgres()) q = "WITH a(v) AS (VALUES(ARRAY['''a''','b']::varchar[]),(ARRAY['abc, def','the \"big\" one','fgh']::varchar[])) SELECT * FROM a" x <- DBI::dbGetQuery(con,q) # Split quoted strings avoiding literal quotes within values xx = gsub("[\\][\"]","%myspecialquote%",x$v) # Protect quoted quotes y = stringi::stri_extract_all_regex(xx, '(?<=[{"]).*?(?=["}])') yy = lapply(y,\(.) gsub("%myspecialquote%","\"",.)) # Put back quotes z = lapply(yy,\(.) .[.!="," & .!=""]) # Remove empty strings and lone commas # Split what wasn't split already w = lapply(1:length(z),\(.) { t = ifelse(grepl("\"",x$v[.]),z[.],strsplit(z[[.]],","))[[1]] t = lapply(t,\(.) ifelse(grepl("^,",.) | grepl(",$",.),(gsub("^[,]|[,]$","",.) |> strsplit(","))[[1]],.)) return(t) }) # Put humpty-dumpty back together again v=sapply(w,\(.) { if(is.list(.)) . = do.call(c,.) return(.) })

	
r regex quotes stringi
1个回答
0
投票

将所有
    ,
  1. 替换为
    ;
    (如果它们未被 
    "
     包围)
    
    删除所有
  2. {
  3. }
  4. \\
  5. 替换为
    \
    沿
  6. ;
  7. 分开
    
    删除尾随
  8. "
  9. 
    
  10. library(stringr) library(magrittr) library(purrr) (x <- data.frame(v = c("{'a',b}", "{\"abc, def\",\"the \\\"big\\\" one\",fgh}"))) # v # 1 {'a',b} # 2 {"abc, def","the \\"big\\" one",fgh} r <- x$v %>% str_replace_all(',(?=(?:[^"]*"[^"]*")*[^"]*$)', ';') %>% str_remove_all("[{}]") %>% str_replace_all("\\\\", "\\") %>% str_split(fixed(";")) %>% map(~ str_remove_all(.x, '^"|"$')) dput(r[[1]]) # c("'a'", "b") dput(r[[2]]) # c("abc, def", "the \"big\" one", "fgh")
最困难的部分是
regex

:


    ,
  1. :匹配逗号
  2. (?=
  3. :这是一个积极的前瞻,可确保以下条件为真。
  4. (?:[^"]*"[^"]*")*
  5. :非捕获组 (
    (?:
    ),匹配双引号对(跳过引号内的内容)。
  6. [^"]*$
  7. :确保逗号之后没有不匹配的双引号(即,我们位于任何引用部分之外)。
    
        
© www.soinside.com 2019 - 2024. All rights reserved.