在R 2.10中提取正则expression式匹配

我试图从string中提取一个数字。

并在这个string“aaaa12xxxx”上做这样的[0-9] +,并得到“12”。

我以为这会是这样的:

> grep("[0-9]+","aaa12xxx", value=TRUE) [1] "aaa12xxx" 

然后我想…

 > sub("[0-9]+", "\\1", "aaa12xxxx") [1] "aaa12xxx" 

但是我得到了一些回应:

 > sub("[0-9]+", "ARGH!", "aaa12xxxx") [1] "aaaARGH!xxx" 

有一个小的细节我失踪请咨询:-)

我正在使用R版本2.10.1(2009-12-14)

谢谢 !


解决scheme的意见

最好的解决scheme是忽略标准函数,并安装Hadley Wickham的stringr包来获得真正有意义的东西。

感谢马立克了解标准图书馆是如何工作的。

使用新的stringr包,它包装所有现有的正则expression式以一致的语法操作并添加一些缺less的:

 library(stringr) str_locate("aaa12xxx", "[0-9]+") # start end # [1,] 4 5 str_extract("aaa12xxx", "[0-9]+") # [1] "12" 

说' 忽略标准函数 '可能有点仓促 – ?gsub的帮助文件甚至在'See also'中也特别引用:

'regmatches'用于基于'regexpr','gregexpr'和'regexec'的结果提取匹配的子string。

所以这会起作用,而且相当简单:

 txt <- "aaa12xxx" regmatches(txt,regexpr("[0-9]+",txt)) #[1] "12" 

也许

 gsub("[^0-9]", "", "aaa12xxxx") # [1] "12" 

你可以使用PERL正则expression式的懒惰匹配:

 > sub(".*?([0-9]+).*", "\\1", "aaa12xx99",perl=TRUE) [1] "12" 

在这种情况下试图replace掉非数字将导致错误。

一种方法是这样的:

 test <- regexpr("[0-9]+","aaa12456xxx") 

现在,请注意regexpr给你的string的开始和结束索引:

  > test [1] 4 attr(,"match.length") [1] 5 

所以你可以使用substr函数的信息

 substr("aaa12456xxx",test,test+attr(test,"match.length")-1) 

我相信有一个更优雅的方式来做到这一点,但这是我能find的最快的方式。 或者,你可以使用sub / gsub去掉你不想离开你想要的东西。

在gsubfn包中使用strapply。 strapply就像是适用于参数是对象,修饰符和函数,除了该对象是一个string(而不是一个数组)的向量,修饰符是一个正则expression式(而不是一个边距):

 library(gsubfn) x <- c("xy13", "ab 12 cd 34 xy") strapply(x, "\\d+", as.numeric) # list(13, c(12, 34)) 

这表示匹配x的每个组件中的一个或多个数字(\ d +),通过as.numeric传递每个匹配。 它返回一个列表,其组件是x的各个组件的匹配向量。 看看输出,我们看到x的第一个分量有一个匹配,它是13,第二个分量x有两个匹配,分别是12和34.请参阅http://gsubfn.googlecode.com获取更多信息。;

使用正则expression式中的捕获括号和replace中的组引用。 括号中的任何东西都会被记住。 然后他们被访问2,第一个项目。 第一个反斜杠在R中转义反斜杠的解释,以便传递给正则expression式parsing器。

 gsub('([[:alpha:]]+)([0-9]+)([[:alpha:]]+)', '\\2', "aaa12xxx") 

另一个scheme

 temp = regexpr('\\d', "aaa12xxx"); substr("aaa12xxx", temp[1], temp[1]+attr(temp,"match.length")[1]) 

这些方法之间的一个重要区别是任何不匹配的行为。 例如,如果在所有位置都不匹配,则regmatches方法可能不会返回与input相同长度的string

 > txt <- c("aaa12xxx","xyz") > regmatches(txt,regexpr("[0-9]+",txt)) # could cause problems [1] "12" > gsub("[^0-9]", "", txt) [1] "12" "" > str_extract(txt, "[0-9]+") [1] "12" NA 

你可以用C ++编写你的正则expression式函数,将它们编译成DLL并从R中调用它们。

  #include <regex> extern "C" { __declspec(dllexport) void regex_match( const char **first, char **regexStr, int *_bool) { std::cmatch _cmatch; const char *last = *first + strlen(*first); std::regex rx(*regexStr); bool found = false; found = std::regex_match(*first,last,_cmatch, rx); *_bool = found; } __declspec(dllexport) void regex_search_results( const char **str, const char **regexStr, int *N, char **out ) { std::string s(*str); std::regex rgx(*regexStr); std::smatch m; int i=0; while(std::regex_search(s,m,rgx) && i < *N) { strcpy(out[i],m[0].str().c_str()); i++; s = m.suffix().str(); } } }; 

在R中调用

 dyn.load("C:\\YourPath\\RegTest.dll") regex_match <- function(str,regstr) { .C("regex_match",x=as.character(str),y=as.character(regstr),z=as.logical(1))$z } regex_match("abc","a(b)c") regex_search_results <- function(x,y,n) { .C("regex_search_results",x=as.character(x),y=as.character(y),i=as.integer(n),z=character(n))$z } regex_search_results("aaa12aa34xxx", "[0-9]+", 5)