使用定界符拆分字符串,除非在括号中,并保留定界符

Split string with delimiter except when in parentheses, and keep the delimiter

我想拆分任意字符串,例如

x <- "(((K05708+K05709+K05710+K00529) K05711),K05712),K05713 K05714 K02554"
# [1] "(((K05708+K05709+K05710+K00529) K05711),K05712),K05713 K05714 K02554"

at delimiter(s)(这里是一个 space 和一个逗号)除非它们在括号内,并且还保留分隔符作为输出的一部分

[[1]]
[1] "(((K05708+K05709+K05710 K00529) K05711),K05712)"                
[2] ",K05713"                          " K05714"                         
[4] " K02554"

这个例子几乎是直接从 IgnacioF 的 (https://whosebug.com/users/5935889/ignaciof) post ,因为这个例子仅仅是对它的扩展,而且在知道的人手中,解决方案也可以。

在单个分隔符的情况下,我可以将其粘贴到输出向量元素中,但同时使用多个分隔符时,它们的身份在拆分时会丢失,所以据我所知这是行不通的。

我试图找到使用先行和对原始 post 解决方案的其他修改来保持定界符的解决方案,但主要是因为我不了解其解决方案而徒劳无功。

你可以使用

x <- "(((K05708+K05709+K05710+K00529) K05711),K05712),K05713 K05714 K02554"
rx <- "(\((?:[^()]++|(?1))*\))(*SKIP)(*F)|(?<=[^\s,])(?=[\s,])"
strsplit(x, rx, perl=TRUE)
# => [[1]]
# => [1] "(((K05708+K05709+K05710+K00529) K05711),K05712)" ",K05713" 
# => [3] " K05714"                                         " K02554"           

这里的模式是(\((?:[^()]++|(?1))*\))(*SKIP)(*F)|(?<=[^\s,])(?=[\s,]),参见its demo online

详情:

  • (\((?:[^()]++|(?1))*\))(*SKIP)(*F) - 第 1 组匹配呈现平衡括号子串的子串:\( 匹配 ((?:[^()]++|(?1))* 匹配零个或多个(* ) () 以外的 1+ 个字符的序列(参见 [^()]++)或整个第 1 组的整个模式(参见子路由调用 (?1)),然后 \) 匹配文字 ) 并且 (*SKIP)(*F) 使正则表达式丢弃整个匹配的文本,同时将正则表达式索引保留在该匹配的末尾,并继续寻找下一个匹配项
  • | - 或
  • (?<=[^\s,])(?=[\s,]) - 空格和逗号以外的字符与空格或逗号字符之间的位置。