Take the 2-minute tour ×

Given this string:


How would I return everything before the second occurrence of "_"?


I am using R.


share|improve this question
Any guarantee that the strings will always have a second _? How do you want to handle cases where there are 0 or 1 underscores? –  Brian Sep 16 '11 at 19:43
It will always have 2 "_"s... guaranteed! The string is a paste of 3 strings using sep="_". –  James Sep 16 '11 at 20:05
add comment

4 Answers

up vote 4 down vote accepted

I think this might do the task (regex to match everything befor the last occurence of _):



> sub('_([^_]*)$', '', "DNS000001320_309.0/121.0_t0")
[1] "DNS000001320_309.0/121.0"
share|improve this answer
Yeah, if the regex-path is walked, sub would be more appropriate than gsub. –  Bart Kiers Sep 16 '11 at 20:11
If there are more than two underscores this will select beyond the second underscore, although apparently that doesn't matter to the OP, so I point it out only for posterity. –  joran Sep 16 '11 at 20:13
Yeah, good point @joran. It may matter to the OP, but he might not be aware of it. –  Bart Kiers Sep 16 '11 at 20:17
add comment

The following script:

s <- "DNS000001320_309.0/121.0_t0"
t <- gsub("^([^_]*_[^_]*)_.*$", "\\1", s)

will print:


A quick explanation of the regex:

^         # the start of the input
(         # start group 1
  [^_]*   #   zero or more chars other than `_`
  _       #   a literal `_`
)         # end group 1
_         # a literal `_`
.*        # consume the rest of the string
$         # the end of the input

which is replaced with:

\\1       # whatever is matched in group 1

And if there are less than 2 underscores, the string is not changed.

share|improve this answer
Wow, really nice, detailed answer (+1). I definitely like your solution better than mine :) –  daroczig Sep 16 '11 at 21:42
add comment

Personally, I hate regex, so luckily there's a way to do this without them, just by splitting the string:

> s <- "DNS000001320_309.0/121.0_t0"      
> paste(strsplit(s,"_")[[1]][1:2],collapse = "_")
[1] "DNS000001320_309.0/121.0"

Although of course this assumes that there will always be at least 2 underscores in your string, so be careful if you vectorize this and that isn't the case.

share|improve this answer
beat me by 12secs :p –  darckeen Sep 16 '11 at 19:46
@darckeen Great minds....as they say. ;) –  joran Sep 16 '11 at 19:49
+1 for strplit - the way I would solve this problem in R. –  daroczig Sep 16 '11 at 21:42
add comment

not pretty but this will do the trick

mystr <- "DNS000001320_309.0/121.0_t0"

mytok <- paste(strsplit(mystr,"_")[[1]][1:2],collapse="_")
share|improve this answer
add comment

Your Answer


