提取正则表达式匹配


111

我正在尝试从字符串中提取数字。

[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"

我缺少一个小细节。

Answers:


167

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

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

3
(几乎)完全满足了我的需求,但是当我开始打字时,?str_extract我发现str_extract_all生活又恢复了。
dwanderson

94

说“ 忽略标准功能 ” 可能有点草率- ?gsub甚至在“另请参见”中特别引用的帮助文件:

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

这样就可以了,而且非常简单:

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



5

一种方法是:

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去除不需要的内容。


5

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

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

2

在gsubfn软件包中使用捆扎。就像应用一样,args是对象,修饰符和函数,除了对象是字符串的向量(而不是数组)并且修饰符是正则表达式(而不是空白):

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


1

另一个解决方案:

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

1

这些方法之间的一个重要区别是任何不匹配的行为。例如,如果在所有位置都没有匹配项,则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

使用unglue软件包,我们将执行以下操作:

# install.packages("unglue")
library(unglue)
unglue_vec(c("aaa12xxx", "aaaARGH!xxx"), "{prefix}{number=\\d+}{suffix}", var = "number")
#> [1] "12" NA

reprex软件包(v0.3.0)创建于2019-11-06

使用convert参数自动转换为数字:

unglue_vec(
  c("aaa12xxx", "aaaARGH!xxx"), 
  "{prefix}{number=\\d+}{suffix}", 
  var = "number", 
  convert = TRUE)
#> [1] 12 NA

0

这个问题的解决方案

library(stringr)
str_extract_all("aaa12xxx", regex("[[:digit:]]{1,}"))
# [[1]]
# [1] "12"

[[:digit:]]:数字[0-9]

{1,}:至少匹配1次


-2

您可以使用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)

4
这完全没有必要。请参阅“thelatemail”或“罗伯特”的答案为内部R.一个简单的解决方案
丹尼尔圈
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.