rubyguides

String#lines in Ruby — Split String Lines Into an Array

str.lines(line_sep = $/, chomp: false) → array

Splits a string into an array of lines based on a separator. By default it splits on "\n" (the global input record separator, $/), returning each line as a separate string element. Use chomp: true to strip the separators from each element in one step.

Splitting on Newlines

With no arguments, lines splits on the default line separator "\n":

"This is line one\nThis is line two\n".lines
# => ["This is line one\n", "This is line two\n"]

Each element keeps the trailing newline by default. That trips people up constantly. If you want clean strings without the line endings, pass chomp: true.

removing line separators with chomp

The chomp: true option strips the separator from every element as it’s split:

"This is line one\nThis is line two\n".lines(chomp: true)
# => ["This is line one", "This is line two"]

This saves you from calling chomp on each element afterward:

# Without chomp: true — manual cleanup needed
File.read("config.txt").lines.map(&:chomp)

# With chomp: true — done in one step
File.read("config.txt").lines(chomp: true)

Custom Separators

You can split on any separator string, not just newlines:

"apple:banana:cherry".lines(':')
# => ["apple:", "banana:", "cherry"]

"word1 word2 word3".lines(' ')
# => ["word1 ", "word2 ", "word3"]

The separator appears at the end of each element when using a custom separator (just like newlines in the default case).

paragraph mode with empty separator

An empty string "" as separator splits on two or more consecutive newlines, giving you paragraphs:

"Para one.\n\nPara two.\n\n\nPara three.".lines('')
# => ["Para one.\n\n", "Para two.\n\n\n", "Para three."]

The trailing newlines stay in each paragraph element. If you want clean paragraphs without the trailing whitespace, chain map(&:strip) or similar afterward.

line separator variations

Ruby handles the common line ending conventions:

# Unix (LF)
"line1\nline2".lines
# => ["line1\n", "line2"]

# Windows (CRLF)
"line1\r\nline2".lines
# => ["line1\n", "line2"]

# Old Mac (CR only — no split happens)
"line1\rline2".lines
# => ["line1\rline2"]

When the separator is "\n", Ruby strips a leading \r before the newline, so \r\n becomes \n in the output. But a lone \r without a following \n does not trigger a split.

empty string and trailing separators

An empty string returns an empty array:

"".lines
# => []

"".lines(chomp: true)
# => []

A string ending with the separator does not produce a trailing empty element. But an extra blank line (double separator) does:

"a\nb\n".lines
# => ["a\n", "b\n"]

"a\nb\n\n".lines
# => ["a\n", "b\n", "\n"]  # blank line becomes an empty string element

Watch out for this when processing files that may or may not have a trailing newline.

Versus each_line

lines and each_line share the same splitting logic, but they differ in what they return:

  • lines — returns a plain Array, no block supported
  • each_line — returns an Enumerator (or self with a block), enabling lazy iteration

If you’re processing a large file and want to avoid loading the whole thing into memory, each_line with a block is the better choice:

File.foreach("large_log.txt").each_line do |line|
  process(line)
end

For smaller files or when you need an array upfront, lines is straightforward.

See Also