rubyguides

String#chop

str.chop -> new_string

The chop method returns a new string with the last character removed. Unlike chop!, this method does not modify the original string — it creates and returns a copy. It is one of several Ruby methods for trimming strings and characters from either end of a value.

Basic usage

# Remove last character
"hello".chop     # => "hell"
"ruby!".chop     # => "ruby"
"".chop          # => ""

# Original unchanged
str = "hello"
puts str         # => "hello"
puts str.chop    # => "hell"
puts str         # => "hello" (still "hello")

Practical examples

The return value is always a new string, leaving the original untouched. This non-destructive behavior makes chop safe to use in method chains and pipelines where you need the original value later. The return is always a new string, even when the input is empty or only one character long.

Path handling

# Remove trailing slash
path = "/home/user/"
path.chop  # => "/home/user"

# Ensure no trailing character
url = "https://example.com/"
url.chop   # => "https://example.com"

Removing a trailing slash from a file path or URL is one of the most practical uses for chop. When building paths dynamically from user input or configuration, an extra separator at the end can break path joins or cause double slashes in constructed URLs.

String cleanup

# Remove trailing newlines (one character)
"line1\n".chop    # => "line1"
"line1\n\n".chop  # => "line1\n" (only removes one!)

# For more control, use chomp
"line1\n".chomp  # => "line1"

Chop removes exactly one character regardless of what it is, while chomp only removes a trailing newline. This distinction matters when you are cleaning up strings that may or may not end with a newline. If the last character is important data, chop will destroy it.

Input processing

# Clean user input
username = gets.chop
# Unlike chomp, removes ANY trailing character

# Process command arguments
args = "arg1 arg2".chop

When reading user input with gets, the string includes the newline character from the Enter key. Using chop removes it unconditionally, which works but is less precise than chomp. Use chop when you know the trailing character is always unwanted.

CSV row processing

# Remove trailing field separator
row = "field1,field2,field3"
row.chop  # => "field1,field2,field3"
# If last char is comma

CSV rows often end with a comma or other field separator. Chop removes the last character regardless of what it is, so it works for cleaning up delimited data rows without needing to check what the trailing character actually contains.

How it differs from chomp

# chop removes exactly ONE character
"hello\n".chop   # => "hello" (removes newline)
"hello\n".chomp  # => "hello" (removes newline)

# Different when no newline
"hello".chop    # => "hell" (removes 'o')
"hello".chomp   # => "hello" (no change, no newline)

The key difference is that chomp only acts on a recognized line separator, defaulting to $/ (typically \n). Chop always removes the last character. If your input might contain a newline at the end, chomp is safer; if you know the last character is a delimiter, chop is more direct.

Edge Cases

# Empty string
"".chop    # => ""

# Single character
"a".chop   # => ""

# Multiple newlines
"a\n\n".chop   # => "a\n" (one newline remains)

An empty string returns an empty string, and a single-character string returns an empty string. Chop handles both edge cases consistently, always producing a valid string result without raising exceptions or returning nil values as a destructive method might.

With regex alternative

# For more control, use regex
"hello".sub(/.$/, '')   # => "hell"
"hello".gsub(/.$/, '')  # => "hell" (if one char)

Regular expressions give you more control over which characters to remove and under what conditions. Chop is simpler and faster when you only need to remove the last character, but regex is better when the removal logic depends on the character’s value.

Performance

# chop is fast and efficient for single char removal
# Creates new string (doesn't modify original)

Choosing chop versus chomp

chop is a good fit when you want exactly one character removed from the end and you do not want to change the original string. That makes it useful for small cleanup tasks, especially when the last character is known to be a delimiter or stray symbol.

# Quick cleanup of a known trailing delimiter
"item1,item2,".chop  # => "item1,item2"

It is not the same as chomp, which is more selective about line endings. If your input might end with a newline, chomp is usually safer; if you truly want the last character gone no matter what it is, chop keeps the intention very direct.

That distinction matters when you are handling file names, prompts, or tiny protocol fragments. The method does one small job and does it consistently, which can be enough when you only need to trim a trailing marker and nothing else. If the input is more varied, though, the extra selectivity from chomp or a regex can save you from removing the wrong character. In short, chop is best when the rule is simple and the ending is already known.

Because it removes only one character, chop is easy to reason about in small cleanup paths. That makes it useful when the value is already almost correct and you just need to remove a final symbol before the next step.

# Chop is safe when the ending is predictable
"config.yaml~".chop  # => "config.yaml"

If you need to process lines from a file or deal with mixed endings, a more selective helper will usually be the better option.

That makes it a neat fit for tiny normalization tasks where the last character is always just decoration. The code stays short, the intent stays plain, and the reader can see that no other part of the string is meant to change. If the ending is not guaranteed, a stricter helper is still the safer call.

Use chop when you need to remove exactly one character from the end of a string without modifying the original.

See Also