我想用数学比较来分割表达式,例如
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",所以这两个=应该作为单个元素返回.如何更改正则表达式以实现此目的?(我已经尝试过"=="的分组和量词,但没有任何效果 - 正则表达式不是我的朋友......)
您可以使用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)
在评论中扩展我的想法,仅用于格式化:
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)
*如果您的条目可以在运营商周围留出空间,您可以在每个捕获组之间添加,如果不是,则操作员捕获将获得它们.
使用单词'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)))"
| 归档时间: |
|
| 查看次数: |
434 次 |
| 最近记录: |