How do I remove all characters in a string until a substring is matched, in Ruby?
Solution 1
or with the regex:
str = "Hey what's up @dude, @how's it going?"
str.gsub!(/.*?(?=@how)/im, "") #=> "@how's it going?"
you can read about lookaround at here
Solution 2
Use String#slice
s = "Hey what's up @dude, @how's it going?"
s.slice(s.index("@how")..-1)
# => "@how's it going?"
Solution 3
There are literally tens of ways of doing this. Here are the ones I would use:
If you want to preserve the original string:
str = "Hey what's up @dude, @how's it going?"
str2 = str[/@how's.+/mi]
p str, str2
#=> "Hey what's up @dude, @how's it going?"
#=> "@how's it going?"
If you want to mutate the original string:
str = "Hey what's up @dude, @how's it going?"
str[/\A.+?(?=@how's)/mi] = ''
p str
#=> "@how's it going?"
...or...
str = "Hey what's up @dude, @how's it going?"
str.sub! /\A.+?(?=@how's)/mi, ''
p str
#=> "@how's it going?"
You need the \A
to anchor at the start of the string, and the m
flag to ensure that you are matching across multiple lines.
Perhaps simplest of all for mutating the original:
str = "Hey what's up @dude, @how's it going?"
str.replace str[/@how's.+/mi]
p str
#=> "@how's it going?"
Solution 4
String#slice
and String#index
work fine but will blow up with ArgumentError: bad value for range if the needle is not in the haystack.
Using String#partition
or String#rpartition
might work better in that case:
s.partition "@how's"
# => ["Hey what's up @dude, ", "@how's", " it going?"]
s.partition "not there"
# => ["Hey what's up @dude, @how's it going?", "", ""]
s.rpartition "not there"
# => ["", "", "Hey what's up @dude, @how's it going?"]
Solution 5
An easy way to get only the part you are interested in.
>> s="Hey what's up @dude, @how's it going?"
=> "Hey what's up @dude, @how's it going?"
>> s[/@how.*$/i]
=> "@how's it going?"
If you really need to change the string object, you could always do s=s[...]
.
oxo
Updated on July 25, 2022Comments
-
oxo almost 2 years
Say I have a string:
Hey what's up @dude, @how's it going?
I'd like to remove all the characters before
@how's
. -
McStretch about 13 years+1 very clean. Aren't the indices off though? Shouldn't it be
0..s.index("@how")
? -
Simone Carletti about 13 yearsHe wants to strip everything before the match, that is the same to say "keep everything after the match".
-
oxo about 13 yearsConsidering that it could be in any case variation of @how (e.g. @How, @HOW, @HoW etc), could it be done like this: str.gsub(/.*?(?=@[Hh][Oo][Ww])/, "")?
-
McStretch about 13 yearsOh whoops, I misunderstood how splice worked. I thought it removed the string in place, like a delete method. I didn't realize it returned the spliced text for use.
-
oxo about 13 yearsI commented below to another answer, but I was wondering that since it could be in any case variation of @how (e.g. @How, @HOW, @HoW etc), could it be done like this: str.slice(str.index("@[Hh][Oo][Ww]")..-1)
-
Nathan Long about 13 yearsIf the search string doesn't appear, the
index
will returnnil
. So he should either check fornil
before doing theslice
, or plan to rescue the error that comes from passing an index ofnil
toslice
. -
Vasiliy Ermolovich about 13 yearssure, fixed. (/i have been added)
-
Phrogz about 13 yearsNo need for
gsub!
whensub!
will do, right? Also note (per my answer) that you need the\A
anchor and/orm
flag in case the string has a newline before the text to match. -
Phrogz about 13 yearsYou need a
m
flag on that last regex to match any newlines that may follow. -
Vasiliy Ermolovich about 13 yearsThanks! Sorry, I don't know the difference between gsub and sub. Could you explain it?
-
Andrew Haust over 6 yearsSuuuuper old and you obviously probably know the difference by now, but would be nice to see the answer changed for n00bs: gsub does a global search and replace while sub stops after the first match. gsub could cause unexpected results or poor performance is longer strings.