2010-02-03 2 views
73

Я пытаюсь извлечь число из строки.Извлечь регулярное выражение, соответствующее

И сделайте что-нибудь наподобие [0-9]+ на строке "aaa12xxx" и получите "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

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

Не нужно PERL, если вы хотите использовать слегка уродливые «[^ 0-9] * ([0-9] +). *" –

2

Использование планки в пакете gsubfn. strapply, как применять в том, что арг являются объектом, модификатор и функции за исключением того, что объект представляет собой вектор строк (а не массив) и модификатор представляет собой регулярное выражение (а не края):

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

Это говорит о том, чтобы соответствовать одной или нескольким цифрам (\ d +) в каждом компоненте x, проходящем каждый матч через 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

одно важное различие между этими подходами поведение с любым не-спичек. Например, метод regmatches не может возвращать строку той же длины, что и вход, если они не совпадают во всех позициях

> 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++, скомпилировать их в 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) 
Смежные вопросы