Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 拆分字符串,但忽略由给定字符包围的分隔符_R_Regex_String Parsing - Fatal编程技术网

R 拆分字符串,但忽略由给定字符包围的分隔符

R 拆分字符串,但忽略由给定字符包围的分隔符,r,regex,string-parsing,R,Regex,String Parsing,我想拆分一个字符串,但仅当它没有被给定的字符集包围时才使用分隔符 当前: strsplit("1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}","\\?") #> [[1]] #> [1] "1 " " 2 " " (3 " " 4) " " {5 " " (6 " " 7)}" 预期: strsplit2 <- function(x, split, fixed = FALSE, perl = FALSE, useBytes = FALSE,

我想拆分一个字符串,但仅当它没有被给定的字符集包围时才使用分隔符

当前:

strsplit("1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}","\\?")
#> [[1]]
#> [1] "1 "   " 2 "  " (3 " " 4) " " {5 " " (6 " " 7)}"
预期:

strsplit2 <- function(x, split, fixed = FALSE, perl = FALSE, useBytes = FALSE,
                      escape = c("()","{}","[]","''",'""',"%%")){
  # ... 
}
strsplit2("1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}","\\?")
#> [[1]]
#> [1] "1 "   " 2 "  " (3 ? 4) " " {5 ? (6 ? 7)}"
我通过一些复杂的解析解决了这个问题,但我担心性能,不知道正则表达式是否可以更快

供参考:

我目前的解决方案与这个问题不太相关,它是:

parse_qm_args <- function(x){
  x <- str2lang(x)
  # if single symbol
  if(is.symbol(x)) return(x)
  i <- numeric(0)
  out <- character(0)
  while(identical(x[[c(i,1)]], quote(`?`)) &&
        (!length(i) || length(x[[i]]) == 3)){
    out <- c(x[[c(i,3)]],out)
    i <- c(2, i)
  }
  # if no `?` was found
  if(!length(out)) return(x)

  if(length(x[[i]]) == 2) {
    # if we have a unary `?` fetch its arg
    out <-  c(x[[c(i,2)]],out)
  } else {
    # if we have a binary `?` fetch the its first arg
    out <-  c(x[[c(i)]], out)
  }
  out
}
*SKIP*FAIL和perl=T是您的朋友:

some_string <- c("1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}")

pattern <- c("(?:\\{[^{}]*\\}|\\([^()]*\\))(*SKIP)(*FAIL)|\\?")
some_parts <- strsplit(some_string, pattern, perl = T)
some_parts
看。这对嵌套构造不起作用。

*SKIP*FAIL和perl=t是您的朋友:

some_string <- c("1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}")

pattern <- c("(?:\\{[^{}]*\\}|\\([^()]*\\))(*SKIP)(*FAIL)|\\?")
some_parts <- strsplit(some_string, pattern, perl = T)
some_parts

看。这对嵌套结构不起作用。

这里是@CodeManiac思想的一个实现,它进行了一些优化并处理了边缘情况


splitter这里是@CodeManiac想法的一个实现,其中包括一些优化和处理边缘情况


splitter最好的方法是使用递归。在这种情况下,您将捕获所有分组的元素,然后在未分组的删除器上拆分:

pattern = "([({'](?:[^(){}']*|(?1))*[')}])(*SKIP)(*FAIL)|\\?"

x1 <- "1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}"
x2 <- "1 ? 2 ? '3 ? 4' ? {5 ? (6 ? 7)}"
x3 <- "1 ? 2 ? '3 {(? 4' ? {5 ? (6 ? 7)}"
x4 <- "1 ? 2 ? '(3 ? 4) ? {5 ? (6 ? 7)}'"

strsplit(c(x1,x2,x3, x4),pattern,perl=TRUE)

 [[1]]
[1] "1 "             " 2 "            " (3 ? 4) "      " {5 ? (6 ? 7)}"

[[2]]
[1] "1 "             " 2 "            " '3 ? 4' "      " {5 ? (6 ? 7)}"

[[3]]
[1] "1 "             " 2 "            " '3 {(? 4' "    " {5 ? (6 ? 7)}"

[[4]]
[1] "1 "                         " 2 "                        " '(3 ? 4) ? {5 ? (6 ? 7)}'"

最好的办法是使用递归。在这种情况下,您将捕获所有分组的元素,然后在未分组的删除器上拆分:

pattern = "([({'](?:[^(){}']*|(?1))*[')}])(*SKIP)(*FAIL)|\\?"

x1 <- "1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}"
x2 <- "1 ? 2 ? '3 ? 4' ? {5 ? (6 ? 7)}"
x3 <- "1 ? 2 ? '3 {(? 4' ? {5 ? (6 ? 7)}"
x4 <- "1 ? 2 ? '(3 ? 4) ? {5 ? (6 ? 7)}'"

strsplit(c(x1,x2,x3, x4),pattern,perl=TRUE)

 [[1]]
[1] "1 "             " 2 "            " (3 ? 4) "      " {5 ? (6 ? 7)}"

[[2]]
[1] "1 "             " 2 "            " '3 ? 4' "      " {5 ? (6 ? 7)}"

[[3]]
[1] "1 "             " 2 "            " '3 {(? 4' "    " {5 ? (6 ? 7)}"

[[4]]
[1] "1 "                         " 2 "                        " '(3 ? 4) ? {5 ? (6 ? 7)}'"

这似乎是相关的:但我不知道如何概括它你的牙套总是平衡的吗?如果是的话,那么最简单的方法就是遍历字符串,跟踪开始大括号和?的位置,只有在到达分隔符且开始大括号和结束大括号相等时才拆分,否则替换?使用输出字符串中所需的+解析总是比反向引用更快,在这里,您的用例需要反向引用,IMO使用简单解析就足以获得您在扩展我的第一条注释时所期望的结果。类似的事情可以很容易地完成,我不认为正则表达式在需要返回引用时可以更快地进行解析,但这种循环很慢,但我想C++可以使用RCPP实现……这似乎是相关的:但是我不知道如何概括你的括号总是平衡的吗?如果是的话,那么最简单的方法就是遍历字符串,跟踪开始大括号和?的位置,只有在到达分隔符且开始大括号和结束大括号相等时才拆分,否则替换?使用输出字符串中所需的+解析总是比反向引用更快,在这里,您的用例需要反向引用,IMO使用简单解析就足以获得您在扩展我的第一条注释时所期望的结果。有些事情可以很容易地完成,我认为ReGEX在需要返回引用时可以更快地进行简单解析,但这种循环在R中很慢,但我想它可以在C++中使用RCPP……:[^ {} ] **?1 * ]使它很慢。此外,似乎可能存在{和}内部的不平衡和不平衡,反之亦然。我会使用一个更精确的正则表达式,有更多的替换,可能是展开的。此外,似乎可能存在{和}内部的不平衡和不平衡,反之亦然。我会使用一个更精确的正则表达式和更多的替换,可能是展开的。
pattern = "([({'](?:[^(){}']*|(?1))*[')}])(*SKIP)(*FAIL)|\\?"

x1 <- "1 ? 2 ? (3 ? 4) ? {5 ? (6 ? 7)}"
x2 <- "1 ? 2 ? '3 ? 4' ? {5 ? (6 ? 7)}"
x3 <- "1 ? 2 ? '3 {(? 4' ? {5 ? (6 ? 7)}"
x4 <- "1 ? 2 ? '(3 ? 4) ? {5 ? (6 ? 7)}'"

strsplit(c(x1,x2,x3, x4),pattern,perl=TRUE)

 [[1]]
[1] "1 "             " 2 "            " (3 ? 4) "      " {5 ? (6 ? 7)}"

[[2]]
[1] "1 "             " 2 "            " '3 ? 4' "      " {5 ? (6 ? 7)}"

[[3]]
[1] "1 "             " 2 "            " '3 {(? 4' "    " {5 ? (6 ? 7)}"

[[4]]
[1] "1 "                         " 2 "                        " '(3 ? 4) ? {5 ? (6 ? 7)}'"