2010-02-03 119 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)