R正则表达式获取第二个下划线之前的所有文本

7
s <- "1-343-43Hello_2_323.14_fdh-99H"

在R中,我想使用正则表达式来获取第二个下划线之前的子字符串。如何使用一个正则表达式实现这个目标?另一种方法是通过下划线进行分割,然后粘贴前两个——类似于这样的操作:
paste(sapply(strsplit(s, "_"),"[", 1:2), collapse = "_")

提供:

[1] "1-343-43Hello_2"

但是我如何编写一个正则表达式来实现相同的功能?

5个回答

9
总的来说,回答标题中的问题是:
sub("^(([^_]*_){n}[^_]*).*", "\\1", s)

其中n是您允许的下划线数量。


实际上,n是下划线数量减1的结果,所以如果你想允许2个下划线,那么n就是1。 - G. Grothendieck
@G.Grothendieck 不,不是。 - logi-kal
你说得没错,但问题是指“在第二个下划线之前的子字符串”,因此n=1而不是2,这就是我试图澄清但显然表述不清楚的地方。无论如何,我还是给了你一个赞,因为你提供了最通用的答案。 - G. Grothendieck

5
您可以使用 sub 标签:
sub("^([^_]*_[^_]*).*", "\\1", s)

查看正则表达式演示

R 代码演示:

s <- "1-343-43Hello_2_323.14_fdh-99H"
sub("^([^_]*_[^_]*).*", "\\1", s)
## => [1] "1-343-43Hello_2"

模式细节

  • ^ - 字符串开头
  • ([^_]*_[^_]*) - 第一组捕获0个或多个非_字符,然后是一个_,再次是0个或多个非_字符。
  • .* - 字符串的其余部分(请注意,TRE正则表达式.也匹配换行符)。

\\1替换仅返回组1中的值。


0
sub('\\_\\d+\\..*$','',s)
#[1] "1-343-43Hello_2"

0
echo preg_replace("/([^_])_([^_]).*/" , "$1_$2" , "1-343-43Hello_2_323.14_fdh-99H");

或者,如果你只是想匹配 int,那么 /^[^]*[^_]*/ 就是用来匹配它的正则表达式字符串。

<?php
    echo preg_match("/^[^_]*_[^_]*/" , "1-343-43Hello_2_323.14_fdh-99H" , $test );
    var_dump( $test );
?>

或者在javascript中

"1-343-43Hello_2_323.14_fdh-99H".match(/^[^_]*_[^_]*/);

1
这个问题明确是关于 R 语言的。 - logi-kal
抱歉,我没有听清楚。 - Tim Holum

0

如果你需要perl=TRUE(例如look-ahead和look-behind),那么在data.table中可以使用gsub进行替换,不幸的是,在str_match中无法实现。

dtx[, var_stringr := stringr::str_match(string, '([^_]+)(?:_[^_]+){5}$')[,2]][]


dtx[
  # first select the ones with '_' so that the third element is NA
  grepl('_', string), 
  var_gsub := sub('(.*_)([^_]+)(_[^_]+){5}$',  '\\2', string)][]

这种方法的缺点是,如果您选择的数字高于第n个出现次数,它不会像str_match一样返回NA,而是返回整个字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接