R 在知道某些子字符串的情况下拆分字符串

R 在知道某些子字符串的情况下拆分字符串,r,regex,R,Regex,假设我有以下字符串和子字符串向量: x <- "abc[[+de.f[-[[g" v <- c("+", "-", "[", "[[") 获取匹配项的一个选项可能是: [a-z.]+匹配1+乘以a-z或点 |或 \[+匹配1+次[ |`或 [+-]匹配+或- | 例如,要获取匹配项,请执行以下操作: library(stringr) x <- "abc[[+de.f[-[[g" str_extract_all(x, "[a-z.]+|\\[+|[+-]") 库(stri

假设我有以下字符串和子字符串向量:

x <- "abc[[+de.f[-[[g"
v <- c("+", "-", "[", "[[")

获取匹配项的一个选项可能是:

  • [a-z.]+
    匹配1+乘以a-z或点
  • |
  • \[+
    匹配1+次
    [
  • |`或
  • [+-]
    匹配
    +
    -
|

例如,要获取匹配项,请执行以下操作:

library(stringr)
x <- "abc[[+de.f[-[[g"
str_extract_all(x, "[a-z.]+|\\[+|[+-]")
库(stringr)

使用
stringr::str\u match\u all
Hmisc::escapeRegex


x这似乎更像是一个词法分析问题,而不是匹配问题。我似乎用

library(minilexer)#devtools::install_github(“coolbutuntible/minilexer”)

模式基于纯正则表达式的解决方案

x <- "abc[[+de.f[-[[g"
v <- c("+", "-", "[", "[[")

## Escaping function
regex.escape <- function(string) {
  gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
## Sorting by length in the descending order function
sort.by.length.desc <- function (v) v[order( -nchar(v)) ]

pat <- paste(regex.escape(sort.by.length.desc(v)), collapse="|")
pat <- paste0("(?s)", pat, "|(?:(?!", pat, ").)+")
res <- regmatches(x, gregexpr(pat, x, perl=TRUE))
## => [[1]]
##    [1] "abc"  "[["   "+"    "de.f" "["    "-"    "[["   "g"
请参见regex演示和Regulex图表:

详细信息

  • (?s)
    -使
    匹配任何字符(包括换行符)的点调用修饰符
  • \[\[
    -
    [[
    子字符串(使用
    regex.escape转义)
  • |
    -或
  • \+
    -a
    +
  • |-
    -或
    -
    (无需转义
    -
    ,因为它不在字符类中)
  • \[
    -或
    [
  • |
    -或
  • (?:(?!\[\[\+\\+-\[)+
    -匹配任何字符(
    )的一种,尽可能多地重复1次或更多次(
    +
    ,在结尾),这不会开始一个
    [
    +
    -
    [
    字符序列(了解更多信息)
<>你也可以考虑一个较少的“正则表达式密集型”的解决方案:
x <- "abc[[+de.f[-[[g"
v <- c("+", "-", "[", "[[")

## Escaping function
regex.escape <- function(string) {
  gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
## Sorting by length in the descending order function
sort.by.length.desc <- function (v) v[order( -nchar(v)) ]
## Interleaving function
riffle3 <- function(a, b) { 
  mlab <- min(length(a), length(b)) 
  seqmlab <- seq(length=mlab) 
  c(rbind(a[seqmlab], b[seqmlab]), a[-seqmlab], b[-seqmlab]) 
} 
pat <- paste(regex.escape(sort.by.length.desc(v)), collapse="|")
res <- riffle3(regmatches(x, gregexpr(pat, x), invert=TRUE)[[1]], regmatches(x, gregexpr(pat, x))[[1]])
res <- res[res != ""]
## => [1] "abc"  "[["   "+"    "de.f" "["    "-"    "[["   "g"   

x谢谢,这可能是正确的选择,但你对我的数据做出了强有力的假设,字符可能是anything@Moody_Mudskipper它基于示例中的字符串。您可以使用希望允许的字符扩展character类。您创建了
[+
进入一个异常,然后手动编码
+
-
,以一种只对单个字符有效的方式,我需要从向量变量开始,使用
lappy对每个字符进行转义(tmp,function(x)paste0(\\”,x,collapse=”“)
?这充满了问题。使用
Hmisc::escapeRegex
使它更干净,它的代码与您的
regex类似。escape
My
regex。在我看来,escape
是最好的,因为它只会转义那些可能需要转义的字符。不过,我不包括空格和
,因为很少使用自由间距模式使用R正则表达式。这几乎是完美的:
temp@Moody\u Mudskipper如果你查看
lex()
的源代码,它基本上也在做
str\u match\u all()
答案中的方法。可能有更好的方法来构建一个合适的快速词法分析器,但这类东西在C级通常更容易。坚持你的答案可能会更容易。谢谢,这就是我使用的方法。我也喜欢这是100%的基R。虽然我没有做基准测试,但事后看来,速度并不是一个真正的问题问题。@Moody_Mudskipper注意到,一个贪婪的令牌会消耗资源,而且速度可能会很慢。但是,这是纯正则表达式的唯一方法,因为您的数据是动态的。如果您事先知道
v
内容,您可以手动优化该模式,但它是用户定义的,没有优化的方法。
library(stringr)
x <- "abc[[+de.f[-[[g"
str_extract_all(x, "[a-z.]+|\\[+|[+-]")
library(minilexer) #devtools::install_github("coolbutuseless/minilexer")

patterns <- c(
  dbracket  = "\\[\\[", 
  bracket   = "\\[",
  plus      = "\\+",
  minus     = "\\-",
  name      = "[a-z.]+"
)

x <- "abc[[+de.f[-[[g"
lex(x, patterns)
unname(lex(x, patterns))
# [1] "abc"  "[["   "+"    "de.f" "["    "-"   
# [7] "[["   "g" 
x <- "abc[[+de.f[-[[g"
v <- c("+", "-", "[", "[[")

## Escaping function
regex.escape <- function(string) {
  gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
## Sorting by length in the descending order function
sort.by.length.desc <- function (v) v[order( -nchar(v)) ]

pat <- paste(regex.escape(sort.by.length.desc(v)), collapse="|")
pat <- paste0("(?s)", pat, "|(?:(?!", pat, ").)+")
res <- regmatches(x, gregexpr(pat, x, perl=TRUE))
## => [[1]]
##    [1] "abc"  "[["   "+"    "de.f" "["    "-"    "[["   "g"
(?s)\[\[|\+|-|\[|(?:(?!\[\[|\+|-|\[).)+
x <- "abc[[+de.f[-[[g"
v <- c("+", "-", "[", "[[")

## Escaping function
regex.escape <- function(string) {
  gsub("([][{}()+*^$|\\\\?.])", "\\\\\\1", string)
}
## Sorting by length in the descending order function
sort.by.length.desc <- function (v) v[order( -nchar(v)) ]
## Interleaving function
riffle3 <- function(a, b) { 
  mlab <- min(length(a), length(b)) 
  seqmlab <- seq(length=mlab) 
  c(rbind(a[seqmlab], b[seqmlab]), a[-seqmlab], b[-seqmlab]) 
} 
pat <- paste(regex.escape(sort.by.length.desc(v)), collapse="|")
res <- riffle3(regmatches(x, gregexpr(pat, x), invert=TRUE)[[1]], regmatches(x, gregexpr(pat, x))[[1]])
res <- res[res != ""]
## => [1] "abc"  "[["   "+"    "de.f" "["    "-"    "[["   "g"