Métodos de String em Ruby: Um Guia Visual e Prático
Aprenda os métodos de string do Ruby de forma visual: índices e fatias, maiúsculas e minúsculas, aparar espaços, métodos com ! e as suas pegadinhas, busca, sub vs. gsub, split e join, alinhar texto, conversões, uma medição real e exercícios com respostas.

Nesta página
Nomes, mensagens, senhas, páginas da web, conversas de chat, arquivos CSV: uma parte enorme do que os programas manipulam é texto. Em Ruby, um pedaço de texto é uma String, e as strings vêm com uma caixa de ferramentas impressionante de métodos prontos para mudar maiúsculas e minúsculas, aparar espaços, buscar, substituir, separar e muito mais.
Neste guia você vai ver como uma string é organizada, conhecer os métodos que vai usar todo dia, aprender os métodos com "bang" (!) e as suas pegadinhas, alinhar um cupom fiscal e medir por que um jeito popular de montar strings fica dramaticamente lento. Exercícios com respostas fecham o artigo.
Todas as saídas abaixo vêm de execuções reais com o Ruby 3.3. Os exemplos usam p para imprimir, porque ele mostra as strings entre aspas, e assim dá para ver cada espaço.
Uma string é uma fileira de caracteres
![Uma string é uma fileira de caracteres, numerada a partir do 0, ou do -1 no fim. A palavra Abacate tem A no índice 0 e e no índice 6, que também é o índice -1. palavra[0, 4] começa no 0 e pega 4 caracteres, dando "Abac". palavra[4..] vai do índice 4 até o fim, dando "ate". palavra[0] é "A", palavra[-1] é "e", e um índice depois do fim, como palavra[20], dá nil em vez de erro](https://nbkmundotech.us-southeast-1.linodeobjects.com/static/images/51b1d522-b98c-448e-bc25-572d589c5003.png?v=1792857620820)
Cada caractere tem uma posição numerada, o seu índice, contando a partir do 0. Índices negativos contam a partir do fim. Os colchetes pegam caracteres ou fatias inteiras:
1palavra = "Abacate"
2p palavra[0]
3p palavra[3]
4p palavra[-1]
5p palavra[0, 4]
6p palavra[0..3]
7p palavra[4..]
8p palavra.length
9p palavra[20]1"A"
2"c"
3"e"
4"Abac"
5"Abac"
6"ate"
77
8nilpalavra[0, 4]quer dizer "comece no 0 e pegue 4 caracteres".palavra[0..3]quer dizer "do índice 0 ao índice 3, incluindo os dois".palavra[4..]quer dizer "do 4 até o fim".
Quantos métodos!
Quantos métodos uma string tem? O próprio Ruby conta:
1puts "Uma string responde a #{"Uma String".methods.size} métodos"
2puts "#{String.instance_methods(false).size} deles são definidos pela própria String"
3p "Uma String".methods.sort.first(8)
4p "Uma String".methods.grep(/case/).sort1Uma string responde a 181 métodos
2133 deles são definidos pela própria String
3[:!, :!=, :!~, :%, :*, :+, :+@, :-@]
4[:casecmp, :casecmp?, :downcase, :downcase!, :swapcase, :swapcase!, :upcase, :upcase!]O grep(/case/) filtra a lista e deixa só os métodos com "case" no nome, um truque útil quando você se lembra do método pela metade. As strings têm mais métodos próprios que qualquer outra classe básica:

Calma, você não vai precisar dos 181. Aqui está um mapa dos que você mais vai usar, agrupados por tarefa:

Maiúsculas e minúsculas
1p "Olá".upcase
2p "MUNDO".downcase
3p "Como VAI você hOJE?".capitalize
4p "Olá Mundo".swapcase
5p "ação e coração".upcase1"OLÁ"
2"mundo"
3"Como vai você hoje?"
4"oLÁ mUNDO"
5"AÇÃO E CORAÇÃO"O capitalize deixa o primeiro caractere maiúsculo e todo o resto minúsculo. E os métodos do Ruby entendem letras acentuadas, não só de A a Z.
Aparando espaços
Textos digitados por pessoas (ou copiados de algum lugar) muitas vezes vêm com espaços sobrando, no começo ou no fim:

1com_espacos = " , E então "
2p com_espacos.lstrip
3p com_espacos.rstrip
4p com_espacos.strip
5p " espaços bagunçados ".squeeze(" ").strip1", E então "
2" , E então"
3", E então"
4"espaços bagunçados"O squeeze(" ") junta sequências de espaços repetidos num só.
Métodos com !: upcase vs. upcase!
Nenhum dos métodos até aqui muda a string original: eles entregam uma string nova. A maioria tem um gêmeo terminado em ! (o "bang") que muda a string no lugar:

1frase = "Eu subi numa árvore."
2outra_frase = frase.upcase
3
4puts "Frase original: #{frase}"
5puts "Outra frase: #{outra_frase}"
6
7frase.upcase!
8puts "Agora a frase: #{frase}"Frase original: Eu subi numa árvore.
Outra frase: EU SUBI NUMA ÁRVORE.
Agora a frase: EU SUBI NUMA ÁRVORE.O #{...} dentro de aspas duplas é a interpolação de strings: o Ruby roda o código entre as chaves e coloca o resultado no texto.
Pegadinha 1: métodos com ! podem devolver nil
Quando não há nada para mudar, um método com ! devolve nil em vez da string:
grito = "OLÁ"
p grito.upcase
p grito.upcase!"OLÁ"
nilEntão nunca encadeie nada depois de um método com !:
nome = "ADA"
puts nome.upcase!.length1encadeado.rb:2:in `<main>': undefined method `length' for nil (NoMethodError)
2
3puts nome.upcase!.length
4 ^^^^^^^("Método length indefinido para nil.")
Pegadinha 2: dois nomes, uma string
Atribuir uma string a uma segunda variável não a copia. Os dois nomes apontam para a mesma string, então mudá-la no lugar por um nome muda também para o outro:

Esse é o verdadeiro motivo para ter cuidado com os métodos ! e com o <<: você pode estar mudando uma string que outras partes do programa ainda estão usando. (Você vai encontrar isso no Exercício 1.)
Pegadinha 3: strings congeladas
Muitos arquivos Ruby começam com um comentário mágico que deixa toda string literal congelada, ou seja, imutável:
1# frozen_string_literal: true
2
3saudacao = "olá"
4saudacao << " mundo"congelada.rb:4:in `<main>': can't modify frozen String: "olá" (FrozenError)("Não dá para modificar a String congelada.") Strings congeladas são mais rápidas e seguras, e as próximas versões do Ruby estão caminhando para congelar os literais por padrão. Quando você precisar de uma string que possa mudar, comece com +"olá" ou "olá".dup.
Montando strings
1nome = "Ada"
2sobrenome = "Lovelace"
3nascimento = 1815
4
5p nome + " " + sobrenome
6p "#{nome} #{sobrenome} nasceu em #{nascimento}"
7p "Ha" * 3
8p nome + ", você faria " + (2026 - nascimento).to_s + " anos em 2026"
9saudacao = +"Olá"
10saudacao << ", " << nome << "!"
11p saudacao
12p format("%-10s|%6.2f", "Pi", 3.14159)1"Ada Lovelace"
2"Ada Lovelace nasceu em 1815"
3"HaHaHa"
4"Ada, você faria 211 anos em 2026"
5"Olá, Ada!"
6"Pi | 3.14"+junta strings, mas os dois lados precisam ser strings, por isso o.to_sno número.- A interpolação
"#{...}"converte sozinha e costuma ficar mais legível. - O
<<(a "pá", shovel) acrescenta numa string existente, mudando-a no lugar. - O
formatdá controle preciso:%-10scompleta o texto até 10 caracteres,%6.2fmostra um número com 2 casas decimais em 6 caracteres.
Por que o += fica lento
Montar uma string grande pedaço por pedaço é comum: um relatório, uma exportação CSV, uma página da web. O inocente relatorio += pedaco tem um custo escondido. A cada vez, o Ruby monta uma string novinha com tudo o que já havia, mais o pedaço novo. Medimos isso:

Com 100.000 pedaços, o += levou 16 segundos, enquanto o << levou menos de 10 milissegundos: umas 1.700 vezes mais rápido. Repare no padrão: dobrar os pedaços de 50.000 para 100.000 mais ou menos quadruplicou o tempo do += (de 4,2 para 16,1 segundos), mas só dobrou o tempo do <<. É isso que "quadrático" quer dizer, e é por isso que o += parece ótimo num teste rápido e depois se arrasta com dados de verdade.
1relatorio = ""
2pedacos.each { |pedaco| relatorio += pedaco } # lento: uma string nova a cada vez
3
4relatorio = +""
5pedacos.each { |pedaco| relatorio << pedaco } # rápido: acrescenta no lugar
6
7relatorio = pedacos.join # rápido e o mais simplesBuscando dentro de uma string
1titulo = "Bem-vindo ao meu mundo"
2p titulo.include?("mundo")
3p titulo.include?("terra")
4p titulo.start_with?("Bem")
5p titulo.end_with?("!")
6p titulo.index("o")
7p titulo.rindex("o")
8p titulo.count("o")
9p titulo.index("terra")1true
2false
3true
4false
58
621
73
8nilMétodos terminados em ? respondem perguntas de sim ou não com true ou false. O index dá a posição da primeira ocorrência (o rindex, da última), e nil quando não há nenhuma.
Substituindo: sub e gsub

1frase = "Eu amo massa, massa e mais massa"
2p frase.sub("massa", "pizza")
3p frase.gsub("massa", "pizza")
4p frase
5p "24/10/2026".gsub("/", "-")
6p "banana".tr("an", "um")
7p "Ligue 5555-1234 ou 5555-9876".gsub(/\d/, "#")
8p "gato rato pato".gsub(/[gr]ato/) { |palavra| palavra.upcase }1"Eu amo pizza, massa e mais massa"
2"Eu amo pizza, pizza e mais pizza"
3"Eu amo massa, massa e mais massa"
4"24-10-2026"
5"bumumu"
6"Ligue ####-#### ou ####-####"
7"GATO RATO pato"- O
subtroca a primeira ocorrência; ogsub(de global) troca todas. Nenhum dos dois muda a original; osub!e ogsub!mudam. - O
trtroca caracteres um por um: todoaviraue todonviram. - Os dois aceitam uma expressão regular (entre barras) para encontrar padrões:
/\d/é "qualquer dígito",/[gr]ato/é "gato ou rato". - Com um bloco, o
gsubdeixa você calcular cada substituição.
Separando e juntando

1p "vermelho,verde,azul".split(",")
2p "a rápida raposa marrom".split
3p "olá".chars
4p ["24", "10", "2026"].join("/")
5p "roma".reverse
6p "um\ndois\ntrês".lines
7p "banana".chars.tally1["vermelho", "verde", "azul"]
2["a", "rápida", "raposa", "marrom"]
3["o", "l", "á"]
4"24/10/2026"
5"amor"
6["um\n", "dois\n", "três"]
7{"b"=>1, "a"=>3, "n"=>2}Quando a string vira um array, todos os métodos de array ficam à sua disposição. O chars.tally conta quantas vezes cada letra aparece.
Alinhando o texto
O ljust, o rjust e o center completam uma string até uma largura fixa, perfeito para tabelas e cupons no terminal:
1itens = { "Café" => 3.5, "Pão de queijo" => 2.25, "Suco de laranja" => 4.0 }
2
3puts "CUPOM".center(26, "=")
4itens.each do |item, preco|
5 puts item.ljust(18, ".") + format("%.2f", preco).rjust(8)
6end
7puts "-" * 26
8puts "TOTAL".ljust(18) + format("%.2f", itens.values.sum).rjust(8)1==========CUPOM===========
2Café.............. 3.50
3Pão de queijo..... 2.25
4Suco de laranja... 4.00
5--------------------------
6TOTAL 9.75Convertendo de e para strings
Texto que vem de usuários ou de arquivos é sempre uma string, mesmo quando parece um número:
1p "42".to_i
2p "3.14".to_f
3p "42abc".to_i
4p "abc".to_i
5p "ruby".to_sym
6p 42.to_s
7p 255.to_s(2)
8begin
9 Integer("42abc")
10rescue ArgumentError => erro
11 puts "O Integer() recusou: #{erro.message}"
12end142
23.14
342
40
5:ruby
6"42"
7"11111111"
8O Integer() recusou: invalid value for Integer(): "42abc"Vazio, em branco e tamanho
1p "".empty?
2p " ".empty?
3p " ".strip.empty?
4p "abc".length
5p "é".length
6p "é".bytesize1true
2false
3true
43
51
62Uma string só de espaços não está vazia, então faça strip antes de verificar se a entrada está em branco. E o length conta caracteres, enquanto o bytesize conta bytes: uma letra acentuada é um caractere, mas dois bytes em UTF-8.
Hora de praticar
Tente fazer estes antes de espiar as respostas.
Exercício 1: Adivinhe a saída (aquecimento). O que as duas linhas com puts imprimem?
1original = +"Ruby"
2mesma_string = original
3mesma_string << "!"
4copia = original.upcase
5puts original
6puts copiaExercício 2: Detector de palíndromos. Escreva palindromo?(texto) ignorando maiúsculas, espaços, pontuação e acentos, para que "Socorram-me, subi no ônibus em Marrocos!" conte.
Exercício 3: Frequência de palavras. Conte quantas vezes cada palavra aparece em "O gato e o rato e O pato", ignorando maiúsculas, e imprima um pequeno gráfico de barras, da mais comum para a menos comum.
Exercício 4: Título. Transforme "o senhor dos ANÉIS" em "O Senhor Dos Anéis".
Exercício 5: Filtro educado. Troque as palavras droga e puxa (com qualquer combinação de maiúsculas) por asteriscos do mesmo tamanho.
Exercício 6: Cifra de César (desafio). Ande cada letra 3 posições no alfabeto (a vira d, e z dá a volta até c), mantendo maiúsculas e minúsculas. Depois decifre de novo.
Quiz rápido
- Qual é a diferença entre
subegsub? - O que
"OLÁ".upcase!devolve, e por quê? - O que
"Abacate"[-1]e"Abacate"[20]dão? - Por que
"42abc".to_ié arriscado para conferir o que o usuário digitou? - Por que
relatorio += pedacofica lento dentro de um laço grande?
Respostas
Exercício 1: As duas variáveis apontam para a mesma string, então o << feito por mesma_string também mudou a original. O upcase (sem !) fez uma cópia separada:
1original = +"Ruby"
2mesma_string = original
3mesma_string << "!"
4copia = original.upcase
5puts original
6puts copiaRuby!
RUBY!Exercício 2: O unicode_normalize(:nfd) separa cada letra acentuada em letra + acento; aí uma expressão regular apaga tudo o que não for letra de a a z (inclusive os acentos), e basta comparar com o inverso:
1def palindromo?(texto)
2 letras = texto.unicode_normalize(:nfd).downcase.gsub(/[^a-z]/, "")
3 letras == letras.reverse
4end
5
6["arara", "Socorram-me, subi no ônibus em Marrocos!", "Ruby"].each do |texto|
7 puts "#{texto.inspect} -> #{palindromo?(texto)}"
8end"arara" -> true
"Socorram-me, subi no ônibus em Marrocos!" -> true
"Ruby" -> falseExercício 3: downcase, split, tally e depois ordenar pela contagem (e em ordem alfabética nos empates):
1texto = "O gato e o rato e O pato"
2contagens = texto.downcase.split.tally
3contagens.sort_by { |palavra, quantidade| [-quantidade, palavra] }.each do |palavra, quantidade|
4 puts "#{palavra.ljust(5)} #{'*' * quantidade} #{quantidade}"
5end1o *** 3
2e ** 2
3gato * 1
4pato * 1
5rato * 1Exercício 4: Separe em palavras, deixe cada uma com inicial maiúscula e junte de volta:
1def titulo(texto)
2 texto.split.map(&:capitalize).join(" ")
3end
4
5puts titulo("o senhor dos ANÉIS")O Senhor Dos AnéisExercício 5: Uma expressão regular montada a partir da lista de palavras: \b marca o limite das palavras, e o i ignora maiúsculas. O bloco mantém o tamanho:
1palavras_bloqueadas = %w[droga puxa]
2mensagem = "Droga, puxa vida, que droga de código!"
3
4limpa = mensagem.gsub(/\b(#{palavras_bloqueadas.join('|')})\b/i) { |palavra| "*" * palavra.length }
5puts limpa*****, **** vida, que ***** de código!Exercício 6: O tr consegue mapear o alfabeto inteiro numa cópia deslocada dele mesmo de uma vez só:
1def cesar(texto, deslocamento)
2 alfabeto = ("a".."z").to_a.join
3 deslocado = alfabeto.chars.rotate(deslocamento).join
4 texto.tr(alfabeto + alfabeto.upcase, deslocado + deslocado.upcase)
5end
6
7segredo = cesar("Olá, Mundo!", 3)
8puts segredo
9puts cesar(segredo, -3)Roá, Pxqgr!
Olá, Mundo!O á passa sem mudar, porque não está no alfabeto de a a z.
Quiz: (1) O sub troca a primeira ocorrência; o gsub troca todas. (2) nil, porque não havia nada para mudar: métodos com ! devolvem nil quando a string continua igual. (3) "e" (o último caractere) e nil (não existe caractere ali). (4) Ele devolve 42 em silêncio, e 0 para texto sem dígitos, então uma entrada inválida parece um número válido; use Integer() para validar. (5) Cada += cria uma string inteira nova com tudo o que já havia, então a cópia cresce com o quadrado da quantidade de pedaços; use << ou join.
Cola rápida
| Eu quero… | Escreva |
|---|---|
| Pegar um caractere / uma fatia | texto[0], texto[-1], texto[0, 4], texto[2..] |
| Mudar maiúsculas e minúsculas | upcase, downcase, capitalize, swapcase |
| Aparar espaços | strip, lstrip, rstrip, squeeze(" ") |
| Mudar a original | a versão com !: upcase!, strip!, gsub! (devolve nil se nada mudar) |
| Inserir valores | "Oi, #{nome}!" |
| Montar uma string grande | relatorio << pedaco ou pedacos.join |
| Buscar | include?, start_with?, end_with?, index, count |
| Trocar a primeira / todas | sub("a", "b") / gsub("a", "b") |
| Separar / juntar | split(","), chars, lines / array.join(", ") |
| Alinhar texto | ljust(10), rjust(10), center(20, "="), format("%.2f", preco) |
| Converter | to_i, to_f, to_s, to_sym, Integer("42") |
| Verificar se está em branco | texto.strip.empty? |
| Achar um método | "texto".methods.grep(/case/) |
Resumindo
Strings estão em todo lugar, e o Ruby tem um método para quase tudo o que você quiser fazer com elas:
- Os índices começam no 0, índices negativos contam a partir do fim, e
[início, tamanho]ou intervalos recortam fatias. - A maioria dos métodos devolve uma string nova. As versões com
!mudam a original, devolvemnilquando nada mudou e afetam todas as variáveis que apontam para aquela string. - O
subtroca uma vez, ogsubem todo lugar, e os dois entendem expressões regulares. - O
splite ojoinlevam de strings para arrays e de volta. ljust,rjust,centereformatalinham o texto.- Monte strings grandes com
<<oujoin, não com+=: com 100.000 pedaços, foram 16 segundos contra menos de 10 milissegundos no nosso teste.
Para mais Ruby, leia O Que É a Linguagem de Programação Ruby?, Arrays em Ruby e Entrada e Saída de Arquivos em Ruby.
Leia a seguir

O Que É a Linguagem de Programação Rust? Um Guia Simples da Linguagem Rápida Que Não Deixa Você Travar
Um guia simples e sem jargões sobre o Rust, a linguagem tão rápida quanto o C que impede famílias inteiras de erros de memória antes de o programa rodar. Entenda a ideia de posse, por que gigantes da tecnologia o adotam e onde ele é usado.

O Que É a Linguagem de Programação Go? Um Guia Simples da Linguagem da Nuvem
Um guia simples e sem jargões sobre o Go, a linguagem simples e rápida que o Google criou para a nuvem. Entenda o que são goroutines, por que um programa Go é um arquivo só e como o Go passou a mover o Docker, o Kubernetes e boa parte da internet.

O Que É a Linguagem de Programação Ruby? Um Guia Simples da Linguagem Feita para a Felicidade
Um guia simples e sem jargões sobre o Ruby, a linguagem de programação feita para deixar os programadores felizes. Entenda por que o código Ruby parece inglês, como o Ruby on Rails move sites como GitHub e Shopify, e onde o Ruby brilha.
Comentários
Seja gentil e específico. Comentários com links de contas novas aparecem depois da análise de um moderador.