提取正则表达式匹配

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

然后在字符串 "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"

我漏掉了一个小细节。

116153 次浏览

对于您的具体情况,您可以删除所有非数字:

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

这在更复杂的情况下不起作用

gsub("[^0-9]", "", "aaa12xxxx34")
# [1] "1234"

一种方法是:

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

现在,注意 regexpr 给出了字符串的起始和结束索引:

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

因此,您可以将这些信息与 subr 函数一起使用

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

我相信还有更优雅的方法但这是我能找到的最快的方法了。或者,您可以使用 sub/gsub 删除您不想留下的您确实想要的内容。

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

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

您可以使用 PERL 正则表达式的延迟匹配:

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

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

在 gsubfn 包中使用 strapp。Strapplication 类似于 application,它的参数是 object、修饰符和函数,只不过 object 是字符串的向量(而不是数组) ,而修饰符是正则表达式(而不是边距) :

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访问。第一个反斜杠转义了 R 中反斜杠的解释,因此它被传递给正则表达式解析器。

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

说“ 忽略标准函数”可能有点草率—— ?gsub的帮助文件甚至在“请参阅”中特别提到:

的结果提取匹配的子字符串 ‘ regexpr’,‘ gregexpr’和‘ regexec’。

因此,这将工作,并且相当简单:

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

另一个解决办法:

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

这些方法之间的一个重要区别是,任何不匹配的行为。例如,如果所有位置都没有匹配项,regmatch 方法可能不会返回与输入长度相同的字符串

> 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 + + 编写正则表达式函数,将它们编译成 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)

使用 解开胶水软件包,我们将执行以下操作:

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

Reprex 软件包于2019-11-06年度创作(0.3.0版)

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

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

这个问题的答案

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

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

{1,} : 至少匹配1次