What is the preferred way of removing the last n
characters from a string?

- 347,512
- 102
- 1,199
- 985

- 46,977
- 48
- 149
- 227
-
If you know the suffix (the top answer suggests a lot come here looking for this), you can use `delete_suffix` from Ruby 2.5. [More info here](https://stackoverflow.com/questions/4209384/ruby-remove-last-n-characters-from-a-string/56803347#answer-56803347). – SRack Jun 28 '19 at 08:22
13 Answers
irb> 'now is the time'[0...-4]
=> "now is the "

- 39,950
- 26
- 134
- 184

- 143,651
- 25
- 248
- 329
-
9Note that this only works in Ruby 1.9. In Ruby 1.8, this will remove the last *bytes*, not the last *characters*. – Jörg W Mittag Nov 17 '10 at 23:20
-
2
-
4This does work, but I am finding 'abc123'.chomp('123') to be twice as fast for both short and very long strings. (Ruby 2.0.0-p247) Can anyone confirm this? – Plasmarob Oct 04 '13 at 16:59
-
14For those wondering why this specific example doesn't work..there are 3 dots not 2 ie `[0...-4]` not `[0..-4]` – rorofromfrance Dec 02 '13 at 17:29
-
1Heh, well, I updated it for 3 dots, but both versions *worked.* Obviously the only question was whether the end of the range specified the index to keep (up to) or the last index to drop. – DigitalRoss Mar 25 '15 at 18:22
-
1Actually, its eather `'now is the time'[0...-4]` (3 dots) yielding `now is the ` or `'now is the time'[0..-4]` (2 dots) yielding `now is the t`. As is, the answer is not completely correct. – Alexander Presber Oct 02 '15 at 07:31
-
1Urk; good catch; fixed. It's correct now. Funny how no one remarked on that until you did. – DigitalRoss Apr 12 '16 at 00:38
-
2@Plamarob I think it's more relevant to say that chomp is 53 nanoseconds faster than it is to say that it is twice as fast. Then you can better estimate the cost vs. value of using it, and whether it might be the thing to optimize in a given situation. – cesoid Jun 10 '16 at 00:03
-
Note that this doesn't work for n == 0. `"123"[0...-0]` is `""` instead of `"123"` – movermeyer May 17 '22 at 14:57
If the characters you want to remove are always the same characters, then consider chomp
:
'abc123'.chomp('123') # => "abc"
The advantages of chomp
are: no counting, and the code more clearly communicates what it is doing.
With no arguments, chomp
removes the DOS or Unix line ending, if either is present:
"abc\n".chomp # => "abc"
"abc\r\n".chomp # => "abc"
From the comments, there was a question of the speed of using #chomp
versus using a range. Here is a benchmark comparing the two:
require 'benchmark'
S = 'asdfghjkl'
SL = S.length
T = 10_000
A = 1_000.times.map { |n| "#{n}#{S}" }
GC.disable
Benchmark.bmbm do |x|
x.report('chomp') { T.times { A.each { |s| s.chomp(S) } } }
x.report('range') { T.times { A.each { |s| s[0...-SL] } } }
end
Benchmark Results (using CRuby 2.13p242):
Rehearsal -----------------------------------------
chomp 1.540000 0.040000 1.580000 ( 1.587908)
range 1.810000 0.200000 2.010000 ( 2.011846)
-------------------------------- total: 3.590000sec
user system total real
chomp 1.550000 0.070000 1.620000 ( 1.610362)
range 1.970000 0.170000 2.140000 ( 2.146682)
So chomp is faster than using a range, by ~22%.

- 1,292
- 1
- 13
- 22

- 103,207
- 26
- 155
- 191
-
5
-
algorithmically, wouldn't something like [0..-#] be faster? a chomp has to parse a string looking for matches. Excluding and end char number doesn't. – Plasmarob Oct 04 '13 at 16:12
-
-
1I found the opposite is actually true. The reality is that .chomp seems consistently to be twice as fast. – Plasmarob Oct 04 '13 at 16:57
-
3@Plamarob, Benchmarks in Ruby are often surprising. I'm so often wrong that I no longer try to guess what will be faster. Also, if the answer would be improved by the benchmark results, please feel free to edit it. – Wayne Conrad Oct 04 '13 at 17:46
-
1If I'm reading the code right, range takes about 53 nanoseconds longer than chomp. It may be a significant drag in certain situations, but keeping the absolute speed in mind (rather than just the relative) might tell you whether you should go through your codebase and change all your ranges into chomps (where applicable). Probably not. – cesoid Jun 09 '16 at 23:51
-
1Works great. And you can use `chomp!()` to act on the String in-place. – Joshua Pinter Mar 23 '18 at 13:38
Ruby 2.5+
As of Ruby 2.5 you can use delete_suffix
or delete_suffix!
to achieve this in a fast and readable manner.
The docs on the methods are here.
If you know what the suffix is, this is idiomatic (and I'd argue, even more readable than other answers here):
'abc123'.delete_suffix('123') # => "abc"
'abc123'.delete_suffix!('123') # => "abc"
It's even significantly faster (almost 40% with the bang method) than the top answer. Here's the result of the same benchmark:
user system total real
chomp 0.949823 0.001025 0.950848 ( 0.951941)
range 1.874237 0.001472 1.875709 ( 1.876820)
delete_suffix 0.721699 0.000945 0.722644 ( 0.723410)
delete_suffix! 0.650042 0.000714 0.650756 ( 0.651332)
I hope this is useful - note the method doesn't currently accept a regex so if you don't know the suffix it's not viable for the time being. However, as the accepted answer (update: at the time of writing) dictates the same, I thought this might be useful to some people.

- 11,495
- 5
- 47
- 60
-
1@JPSilvashy I've never been more pleased to lose a checkmark. This is a great answer. – Wayne Conrad Jul 12 '19 at 19:29
-
4This is a great and fast function, but this is not the right answer because it doesn't answer the question which is exactly `What is the preferred way of removing the last n characters from a string?` – Sam Sep 02 '19 at 10:55
-
1Thanks for the feedback @Sam - this question's had an answer for almost nine years that worked the same as this one, with 261 upvotes at the time of writing. JP accepted that and recently switched to this, so I'd say it answered _their_ question :) I thought I'd pop this in as a modern alternative, and hope it helps people who land here. In fact, I've covered all this in the question - I'm hoping this method accepts a regex soon, though there's a perfect alternative for your case right below this. – SRack Sep 02 '19 at 15:07
str = str[0..-1-n]
Unlike the [0...-n]
, this handles the case of n=0.

- 34,866
- 14
- 107
- 142
-
5Note that this only works in Ruby 1.9. In Ruby 1.8, this will remove the last *bytes*, not the last *characters*. – Jörg W Mittag Nov 17 '10 at 23:21
-
5This is better than the chosen answer, since 3 dots (...) is easier to memorize since -n means take out n characters from the end of the string. – lulalala Nov 03 '11 at 04:24
-
also "abcd"[0..-2] #=> "abc" while "abcd"[0...-2] #=> "ab". In my opinion the 3 dots range option results in a more self explanatory code. – mokagio Jul 29 '13 at 08:56
-
1Note that this doesn't work for n == 0. `str[0...-0]` is `""` instead of `"123"`. You actually want `str[0..-(n+1)]` – movermeyer May 17 '22 at 15:14
-
@movermeyer your edit was rejected by JS and Bash fans. I'm sorry, SO is **** and 90% of people are here only to reject the edits, close and delete questions and answers. You can read my profile info for more and to understand why I'm not an active contributor anymore. You've spotted a real bug in my answer made 11 years ago, well done. I've reaccepted the edit and changed it a bit. – Nakilon May 29 '22 at 13:03
I would suggest chop
. I think it has been mentioned in one of the comments but without links or explanations so here's why I think it's better:
It simply removes the last character from a string and you don't have to specify any values for that to happen.
If you need to remove more than one character then chomp
is your best bet. This is what the ruby docs have to say about chop
:
Returns a new String with the last character removed. If the string ends with \r\n, both characters are removed. Applying chop to an empty string returns an empty string. String#chomp is often a safer alternative, as it leaves the string unchanged if it doesn’t end in a record separator.
Although this is used mostly to remove separators such as \r\n
I've used it to remove the last character from a simple string, for example the s
to make the word singular.

- 5,321
- 4
- 44
- 66
-
1Wouldn't that just remove that single last character? The question is about "characters" in plural – maetthew Feb 10 '13 at 02:54
-
1Yes, you're right, but chomp('chars') will remove the last 'chars'. It wasn't clear to me if the OP wanted specific characters or just N characters. – kakubei Feb 11 '13 at 08:43
-
Yeah, this is the answer, only when you want to remove only one character (which was the case with me though). – Quv Jun 16 '17 at 01:47
name = "my text"
x.times do name.chop! end
Here in the console:
>name = "Nabucodonosor"
=> "Nabucodonosor"
> 7.times do name.chop! end
=> 7
> name
=> "Nabuco"

- 7,474
- 5
- 39
- 59
-
Is this efficient? Seems one worth a benchmark comparison to other answers :) – SRack Sep 02 '19 at 15:19
Dropping the last n
characters is the same as keeping the first length - n
characters.
Active Support includes String#first
and String#last
methods which provide a convenient way to keep or drop the first/last n
characters:
require 'active_support/core_ext/string/access'
"foobarbaz".first(3) # => "foo"
"foobarbaz".first(-3) # => "foobar"
"foobarbaz".last(3) # => "baz"
"foobarbaz".last(-3) # => "barbaz"

- 1,693
- 1
- 19
- 21
-
3Rails 6.0 has a deprication wraning on `"foobarbaz".first(-3)` "Calling String#first with a negative integer limit will raise an ArgumentError in Rails 6.1." – Toby 1 Kenobi Aug 31 '20 at 02:29
if you are using rails, try:
"my_string".last(2) # => "ng"
[EDITED]
To get the string WITHOUT the last 2 chars:
n = "my_string".size
"my_string"[0..n-3] # => "my_stri"
Note: the last string char is at n-1. So, to remove the last 2, we use n-3.

- 125
- 1
- 3
-
2
-
1You don't need to measure the string first, ruby uses negative indexes from the end of the string natively – Devon Parsons Nov 25 '16 at 15:18
Check out the slice()
method:

- 383
- 3
- 16

- 32,456
- 5
- 63
- 68
-
2Note that this only works in Ruby 1.9. In Ruby 1.8, this will remove the last *bytes*, not the last *characters*. – Jörg W Mittag Nov 17 '10 at 23:21
You can always use something like
"string".sub!(/.{X}$/,'')
Where X
is the number of characters to remove.
Or with assigning/using the result:
myvar = "string"[0..-X]
where X
is the number of characters plus one to remove.

- 34,866
- 14
- 107
- 142

- 50,406
- 14
- 85
- 110
If you're ok with creating class methods and want the characters you chop off, try this:
class String
def chop_multiple(amount)
amount.times.inject([self, '']){ |(s, r)| [s.chop, r.prepend(s[-1])] }
end
end
hello, world = "hello world".chop_multiple 5
hello #=> 'hello '
world #=> 'world'

- 5,542
- 2
- 34
- 54
Using regex:
str = 'string'
n = 2 #to remove last n characters
str[/\A.{#{str.size-n}}/] #=> "stri"

- 9,323
- 2
- 24
- 35
x = "my_test"
last_char = x.split('').last

- 59,313
- 13
- 108
- 143
-
3question was about removing last N characters from a string, not about finding the last character – unnitallman Oct 20 '12 at 06:30