在数学比较的分裂字符传染媒介签到R

Dan*_*iel 14 regex r

我想用数学比较来分割表达式,例如

unlist(strsplit("var<3", "(?=[=<>])", perl = TRUE))
unlist(strsplit("var==5", "(?=[=<>])", perl = TRUE))
unlist(strsplit("var>2", "(?=[=<>])", perl = TRUE))
Run Code Online (Sandbox Code Playgroud)

结果是:

[1] "var" "<"   "3"  
[1] "var" "="   "="   "5"  
[1] "var" ">"   "2"  
Run Code Online (Sandbox Code Playgroud)

对于上面的第二个例子,我想得到[1] "var" "==" "5",所以这两个=应该作为单个元素返回.如何更改正则表达式以实现此目的?(我已经尝试过"=="的分组和量词,但没有任何效果 - 正则表达式不是我的朋友......)

Wik*_*żew 9

您可以使用PCRE正则表达式来匹配您需要的子字符串:

==|[<>]|(?:(?!==)[^<>])+
Run Code Online (Sandbox Code Playgroud)

要同时支持!=,请将其修改为

[!=]=|[<>]|(?:(?![=!]=)[^<>])+
Run Code Online (Sandbox Code Playgroud)

请参阅正则表达式演示.

细节:

  • ==- 2个=标志
  • | - 要么
  • [<>]- 一个<>
  • | - 要么
  • (?:(?!==)[^<>])+- 除了<>([^<>])之外的一个或多个字符,它们不启动==char序列(一个淬火的贪婪令牌).

注意:通过添加更多替代方案并调整淬火贪婪令牌,可以轻松扩展.

R测试:

> text <- "Text1==text2<text3><More here"
> res <- regmatches(text, gregexpr("==|[<>]|(?:(?!==)[^<>])+", text, perl=TRUE))
> res
[[1]]
[1] "Text1"     "=="        "text2"     "<"         "text3"     ">"        
[7] "<"         "More here"
Run Code Online (Sandbox Code Playgroud)


Ten*_*bai 6

在评论中扩展我的想法,仅用于格式化:

tests=c("var==5","var<3","var.name>5")
regmatches(tests,regexec("([a-zA-Z0-9_.]+)(\\W+)([a-zA-Z0-9_.]+)",tests))
Run Code Online (Sandbox Code Playgroud)

\w[a-zA-Z0-9_]\W它相反[^a-zA-Z0-9_],我在评论后扩展它包括.在字符类中,并且因为R不支持基类正则表达式中的字符类\ w(需要使用perl = TRUE).

所以正则表达式搜索至少1个\ w和.,然后至少1个不在\ w(匹配运算符),然后至少1个\ w和点.

捕获每个步骤,这给出:

[[1]]
[1] "var==5" "var"    "=="     "5"     

[[2]]
[1] "var<3" "var"   "<"     "3"    

[[3]]
[1] "var.name>5" "var.name"   ">"          "5"       
Run Code Online (Sandbox Code Playgroud)

*如果您的条目可以在运营商周围留出空间,您可以在每个捕获组之间添加,如果不是,则操作员捕获将获得它们.


Cat*_*ath 5

使用单词'boundary(\\b)并指定2种可能性:

unlist(strsplit("var==5", "(?=(\\b[^a-zA-Z0-9])|(\\b[a-zA-Z0-9]\\b))", perl = TRUE))
[1] "var" "=="  "5" 

unlist(strsplit("var<3", "(?=(\\b[^a-zA-Z0-9])|(\\b[a-zA-Z0-9]\\b))", perl = TRUE))
[1] "var" "<"   "3"
unlist(strsplit("var>2", "(?=(\\b[^a-zA-Z0-9])|(\\b[a-zA-Z0-9]\\b))", perl = TRUE))
[1] "var" ">"   "2"
Run Code Online (Sandbox Code Playgroud)

说明:

在"单词"的末尾分割,之后,有一个非字母数字字符\\b[^a-zA-Z0-9]或它是"单词"的结尾,之后有一个字母数字字符.

编辑:

实际上,如果最后的数字是10或更多,上面的代码会有意想不到的结果.
另一个选择是使用lookbehind和拆分之前,之前有一个非字母字符后跟一个字边,或一个字母字符后跟一个字边:

strsplit("var<20", "(?<=(([^a-zA-Z0-9]\\b)|([a-zA-Z0-9]\\b)))", perl = TRUE)[[1]]
#[1] "var" "<"   "20"
strsplit("var==20", "(?<=(([^a-zA-Z0-9]\\b)|([a-zA-Z0-9]\\b)))", perl = TRUE)[[1]]
#[1] "var" "=="  "20"
strsplit("var!=5", "(?<=(([^a-zA-Z0-9]\\b)|([a-zA-Z0-9]\\b)))", perl = TRUE)[[1]]
#[1] "var" "!="  "5"
Run Code Online (Sandbox Code Playgroud)

EDIT2:

完全窃取@Tensibai方式来定义alphanum(+下划线)/非alphanum字符,上面的内容regex可以简化为:"(?<=((\\W\\b)|(\\w\\b)))"