You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中正确拆分带部分引号的逗号分隔字符串?

处理PostgreSQL返回的特殊格式字符串拆分问题

问题场景

在R语言中,处理从PostgreSQL查询得到的data.frame列时,会遇到一种特殊格式的字符串:它们是逗号分隔的列表,但仅当值包含空格、双引号或逗号时才用双引号包裹;值中的字面双引号用\"转义。由于无法修改PostgreSQL端的输出格式,直接按逗号拆分这些字符串会因特殊字符干扰导致错误。需要正确拆分如下示例:

  • 输入{'a',b},拆分结果为c("'a'","b")
  • 输入{"abc, def","the \\\"big\\\" one",fgh},拆分结果为c("abc, def","the \"big\" one","fgh")

原繁琐实现方案

之前曾实现了一套逻辑复杂的处理代码:

# 从PostgreSQL查询创建data.frame
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)

# 拆分带引号的字符串,避开值内部的转义引号
xx = gsub("[\\][\"]","%myspecialquote%",x$v) # 保护转义引号
y = stringi::stri_extract_all_regex(xx, '(?<=[{"]).*?(?=["}])')
yy = lapply(y,\(.) gsub("%myspecialquote%","\"",.)) # 恢复引号

z = lapply(yy,\(.) .[.!="," & .!=""]) # 移除空字符串和单独的逗号

# 拆分未被正确拆分的部分
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)
})

# 合并结果
v=sapply(w,\(.) { 
  if(is.list(.)) 
    . = do.call(c,.)
  return(.)
})

优化后的简洁方案

基于整理的优化建议,这里提供一套更简洁的实现方式(注意需要确保原始值中不包含%myspecialquote%这个自定义标记):

x <- data.frame(v = c("{'a',b}", '{"abc, def","the \\\"big\\\" one",fgh}'))

out <- transform(x, v = lapply(v, function(x) x |>
  gsub("^[{]|[}]$", "", x = _) |>  # 移除首尾的大括号
  gsub("[\\][\"]","%myspecialquote%",x = _) |>  # 替换转义引号为临时标记
  scan(text = _, quote = '"', what = "", sep = ",", quiet = TRUE) |>  # 用scan处理带引号的拆分
  gsub("%myspecialquote%","\"",x = _)  # 恢复转义引号
))

如果使用tidyverse生态,可以将代码中的transform替换为mutate。

内容的提问来源于stack exchange,提问作者David M. Kaplan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:10:12