9

我有以下正则表达式,我想抓住从句子开头到第一个的所有内容##。我可以strsplit像我演示的那样使用它来完成这项任务,但我更喜欢一个gsub解决方案。如果gusub不是正确的工具(我认为是),我更喜欢基本解决方案,因为我想学习基本的正则表达式工具。

x <- "gfd gdr tsvfvetrv erv tevgergre ## vev fe ## vgrrgf"

strsplit(x, "##")[[c(1, 1)]]  #works

gsub("(.*)(##.*)", "\\1", x)  #I want to work
4

6 回答 6

17

只需添加一个字符,?在第一个量词之后加上一个使其“非贪婪”:

gsub("(.*?)(##.*)", "\\1", x) 
# [1] "gfd gdr tsvfvetrv erv tevgergre "

这是相关文档,来自?regex

默认情况下,重复是贪婪的,因此使用最大可能的重复次数。可以通过附加“?”将其更改为“最小”。到量词。

于 2012-11-28T15:56:41.197 回答
4

我会说:

sub("##.*", "", x)

删除所有内容,包括第一次出现##.

于 2012-11-28T15:53:07.950 回答
4

在这种情况下,我会反过来说,即用#空字符串替换后面的所有内容:

gsub("#.*$", "", x)
[1] "gfd gdr tsvfvetrv erv tevgergre "

但是您也可以使用 non-greedy 修饰符?使您的正则表达式按照您建议的方式工作:

gsub("(.*?)#.*$", "\\1", x)
[1] "gfd gdr tsvfvetrv erv tevgergre "
于 2012-11-28T15:54:04.583 回答
3

这是另一种使用更多字符串工具而不是更复杂的正则表达式的方法。它首先找到第一个 ## 的位置,然后提取到该点的子字符串:

library(stringr)
x <- "gfd gdr tsvfvetrv erv tevgergre ## vev fe ## vgrrgf"
loc <- str_locate(x, "##")
str_sub(x, 1, loc[, "start"] - 1)

一般来说,我认为这种循序渐进的方法比复杂的正则表达式更易于维护。

于 2012-11-28T16:48:01.853 回答
1

试试这个作为你的正则表达式

^[^#]+

从字符串的开头开始并匹配任何不 a#到第一个的#

于 2012-11-28T15:50:55.423 回答
1

这里已经有几个更简单的答案,但是由于您在问题中指出您想了解基础 R 中的正则表达式支持,所以这是另一种方式,使用积极的前瞻性断言(?=#)和非贪婪选项(?U)

regmatches(x, regexpr('(?U)^.+(?=#)', x, perl=TRUE))
[1] "gfd gdr tsvfvetrv erv tevgergre "
于 2012-11-28T16:02:42.550 回答