2010-02-03 81 views
73

我试图从字符串中提取数字。提取正则表达式匹配

然后在字符串"aaa12xxx"上做一些类似[0-9]+的并获得"12"

我认为这将是这样的:

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

然后我想通......

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

,但我得到了某种形式的回应做:

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

有我错过了一个小细节。

回答

120

使用新stringr包里面封装了所有现有的正则表达式中一个一致的语法操作,并增加了一些被遗漏:

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

(几乎)正是我需要的,但正如我开始键入'?str_extract'我看到'str_extract_all'和生活是再好不过了。 – dwanderson 2017-06-22 21:36:05

19

也许

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

一种方法是这样的:

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

现在,通知regexpr给你的起点和字符串的结尾指数:

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

这样你就可以使用substr功能的信息

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

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

9

您可以使用PERL regexs'懒惰匹配:

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

在这种情况下尝试替换非数字将导致错误。

+2

如果你愿意使用稍微丑陋的“[^ 0-9] *([0-9] +)”,则不需要PERL。*“ – 2010-02-04 03:29:41

2

在gsubfn软件包中使用strapply。 strapply就像应用,所述ARG游戏对象,改性剂和功能不同的是,对象是字符串(而不是数组)的矢量和改性剂是正则表达式(而不是余量):

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

2

使用捕获正则表达式中的括号和替换中的组引用。括号中的任何内容都会被记住。然后他们被访问2,第一项。第一个反斜杠在R中转义反斜杠的解释,以便传递给正则表达式解析器。

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

这可能是有点仓促地说“忽略的标准功能” - 在“又见”为?gsub甚至专门引用帮助文件:

“regmatches”提取匹配子字符串基于 'regexpr','gregexpr'和'regexec'的结果。

所以这会的工作,并且是相当简单:

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

另一种解决方案:这些方法的行为与任何非比赛之间

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

一个重要的区别。例如,如果没有在所有位置

> 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 
0

你可以写C++的正则表达式功能的匹配regmatches方法可能不会返回相同的长度,输入一个字符串,编译成一个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)