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 plainArray, no block supportedeach_line— returns an Enumerator (orselfwith 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
- /reference/string-methods/string-split/ — general-purpose splitting on any delimiter
- /reference/string-methods/each-line/ — lazy iterator version of
lines - /reference/string-methods/chomp/ — remove trailing separators from a string