Ir para o conteúdo
Allin

Filtrar linhas por um padrão sem linha de comandos

Publicado a 07/08/2026 · 11 min de leitura · Ferramentas de texto e idioma

Daniel Okonkwo

Daniel OkonkwoProgramador front-end e redator de Tecnologia na Allin

Desempenho web · Formatos de ficheiro

Verificado a partir de 3 fontes

Ver perfil
Em resumo

O filter-lines divide o seu texto pelas quebras de linha, testa em cada linha a presença de uma subcadeia, e mantém-na ou descarta-a. A comparação é um includes de string sobre um termo literal: não há motor de expressões regulares por trás da caixa. Escrever ^ERROR num registo não devolveu nada; ERROR|WARN também não; [a-z]+ também não. Cada um produziu um painel de saída vazio, sem mensagem de erro e sem aviso de que o padrão fora lido literalmente, e é esse o comportamento a conhecer antes de começar. O contrário também é verdade e é mais tranquilizador: uma expressão regular inválida é inofensiva aqui, porque não é uma expressão regular. Escrever um simples parêntese de abertura manteve a linha que contém um, exatamente como quereria. «Ignorar maiúsculas» está ativo por omissão: filtrar por apple manteve a linha APPLE juice tanto quanto apple pie; o grep num terminal distingue maiúsculas por omissão e esta ferramenta não, diferença a ter presente se está habituado a uma das duas. A ação oferece «Manter linhas correspondentes» e «Remover linhas correspondentes», que correspondem a grep e grep -v. Deixar o termo vazio devolve o seu texto inalterado, e não nada. Dois detalhes dos ensaios: o modo remover mantém as linhas vazias, porque uma linha vazia não contém o seu termo, portanto um registo filtrado volta com os buracos deixados pelas linhas retiradas; e toda a saída é unida com quebras simples, pelo que um ficheiro Windows perde os retornos de carro pelo caminho.

Isto é o grep para quem não usa grep, com uma diferença importante: a procura é uma subcadeia literal, pelo que uma expressão regular a sério devolve uma caixa vazia e nenhum erro. Cada afirmação foi verificada executando a ferramenta.

O que faz o grep, e que metade está aqui

O grep lê um texto linha a linha, confronta cada linha com um padrão, e escreve as linhas que correspondem. A especificação POSIX define-o assim e define o padrão como uma expressão regular: uma pequena linguagem em que um acento circunflexo significa «início de linha», uma barra vertical «ou então», os parênteses retos «qualquer um destes carateres» e um mais «uma ou mais vezes o que vem antes». A opção de inversão vira o teste e imprime as linhas que não correspondem. A ideia tem uns quarenta anos e continua a ser a via mais rápida para responder a uma pergunta sobre um ficheiro de registo.

O filter-lines implementa o ciclo e a opção de inversão, e para por aí. A linguagem de padrões não está implementada, e sobretudo não está implementada pela metade: o termo que escreve é comparado como uma sequência de carateres, inteira e inalterada. É um desenho legítimo para uma caixa numa página web — a maioria de quem filtra uma lista quer as linhas que contêm a palavra fatura, não uma gramática — mas significa que as duas ferramentas recebem a mesma entrada e dão respostas diferentes, e a que se engana nunca o diz.

A caixa vazia, e porque está vazia

Passaram-se três padrões pelo mesmo registo de sete linhas. ^ERROR não devolveu nada, embora duas linhas comecem por ERROR, porque nenhuma linha contém um acento circunflexo literal seguido das letras E, R, R, O, R. ERROR|WARN não devolveu nada, embora o registo tenha um de cada, porque nenhuma linha contém uma barra vertical literal entre essas duas palavras. [a-z]+ não devolveu nada, pela mesma razão: nenhuma linha contém um parêntese reto. Em todos os casos o painel de saída estava simplesmente vazio. Nada foi destacado, nada foi assinalado e nada sugeriu que o termo tivesse sido lido de forma diferente da pretendida.

É este o modo de falha que importa, e é o inverso do que a expressão «regex inválida» sugeriria. Um padrão malformado é o caso seguro. Escrever um simples parêntese de abertura — o que faria um motor de expressões regulares lançar um erro de grupo por fechar — manteve a linha que contém um parêntese e devolveu-a. O mesmo com um ponto solto, que na linguagem das expressões regulares significa «qualquer carácter» e aqui significa «um ponto»: sobre uma lista com a.b e aXb devolveu apenas a.b. Se se apanhar a escrever sintaxe de expressão regular nesta caixa, o reflexo a construir é olhar para a saída e perguntar-se se um resultado vazio é plausível, porque a ferramenta não o perguntará por si.

Caixa, acentos e o espaço que não queria escrever

«Ignorar maiúsculas» está ativo de fábrica e põe em minúsculas tanto a linha como o termo antes de comparar. Filtrar uma lista de cinco frutas por apple manteve apple pie, APPLE juice e pineapple tart; desligar o interruptor descartou APPLE juice e manteve as outras duas. A linha do pineapple lembra que isto é um teste de subcadeia e não de palavra: apple está dentro de pineapple, portanto a linha corresponde, e não há opção de «palavra inteira» que o impeça. Se precisa de fronteiras de palavra, acrescente os espaços à volta do seu termo e aceite que lhe escapará a palavra no início ou no fim de uma linha.

Das mesmas provas saíram duas armadilhas menores. Um espaço no início do termo faz parte do termo: filtrar a mesma lista por «espaço + apple» não devolveu nada, porque nenhuma linha tem um espaço antes dessa palavra na posição testada. E os acentos seguem a regra do artigo sobre duplicados: um termo cuja letra acentuada se escreve como letra mais marca combinante não encontrou nada numa lista cuja letra acentuada é um único ponto de código, embora as duas pareçam idênticas na caixa de procura. Ambas voltam à mesma disciplina: o que escreveu é comparado exatamente como escreveu, incluindo as partes que não vê.

O modo remover deixa buracos

Mude a ação para «Remover linhas correspondentes» e a ferramenta descarta cada linha que contém o seu termo e mantém tudo o resto — incluindo as linhas vazias, porque uma linha vazia não contém o seu termo. Passe-o por um registo com uma linha vazia entre duas entradas e a linha vazia continua lá depois. Não é um defeito, é a leitura honesta da instrução, mas o resultado raramente se parece com o esperado, e um ficheiro filtrado com uma dúzia de buracos órfãos é incómodo de ler. O remédio é mais um passo: passe o remove-blank-lines pela saída.

Mais um comportamento em que confiar: um termo vazio devolve o seu texto inalterado, não um resultado vazio. Parece óbvio, mas a leitura contrária — sem termo, nada corresponde, nada sai — seria igualmente defensável e esvaziaria em silêncio a sua entrada sempre que limpasse o campo para escrever outra procura. A ferramenta escolhe o ramo mais seguro, e isso foi verificado: com o campo vazio, voltaram as cinco linhas da lista de teste.

Que fazer quando precisa mesmo de um padrão

A maioria das perguntas de padrão pode ser reescrita como perguntas de subcadeia. «Linhas que começam por um código» passa a «linhas que contêm esse código», mais frouxo mas em geral suficiente num registo onde o código só aparece no início de qualquer modo. «Qualquer uma de duas palavras» passa a duas passagens — filtre pela primeira, anote o resultado, filtre o original pela segunda — porque não há alternância. «Um intervalo de carateres» costuma passar a várias passagens, ou diretamente a outra ferramenta. Quando a resposta precisa mesmo de uma gramática, o conselho honesto é que uma caixa de texto num navegador é o instrumento errado, e o certo é um terminal ou um editor de texto com procura por expressão regular.

Uma ressalva sobre a ferramenta irmã. O find-and-replace, neste mesmo site, também recebe um termo literal: faz escape a cada carácter com significado especial antes de construir o seu padrão, o que foi lido no código e confirmado. Portanto, se esperava usá-lo para simular um filtro por expressão regular, não pode. As duas ferramentas são coerentes entre si, essa é a boa notícia; nenhuma das duas é o grep, essa é a notícia de que precisava antes de começar.

Termos escritos no campo «Contém», e o que a ferramenta devolveu de facto
Termo escritoO que voltaPorquê
apple, «Ignorar maiúsculas» ativo (por omissão)apple pie, APPLE juice e pineapple tartAmbos os lados são postos em minúsculas, e o teste é de subcadeia, não de palavra inteira
apple, «Ignorar maiúsculas» desligadoapenas apple pie e pineapple tartAPPLE juice já não contém os carateres exatos escritos
^ERROR sobre um registo cujas duas primeiras linhas começam por ERRORSaída vazia, nenhuma mensagem de erroNenhuma linha contém um acento circunflexo literal seguido dessas cinco letras
ERROR|WARN sobre o mesmo registoSaída vaziaNão há alternância; a barra vertical é apenas um carácter a procurar
Um simples parêntese de aberturaA linha que contém um parêntese — funcionaUma expressão regular inválida é o caso seguro, porque nenhuma é compilada
Um ponto solto, sobre uma lista com a.b e aXbapenas a.bO ponto corresponde a um ponto, não a qualquer carácter
Um campo «Contém» vazioO texto inteiro, inalteradoA ferramenta sai logo em vez de filtrar tudo
Qualquer termo, no modo «Remover linhas correspondentes», sobre um texto com linhas vaziasAs linhas vazias sobrevivemUma linha vazia não contém o termo, portanto não é uma correspondência a remover
Filtrar linhasMantenha ou remova as linhas que contêm uma palavra ou frase.Experimentar a ferramenta

Perguntas frequentes

Posso usar uma expressão regular no campo «Contém»?
Não. O termo é comparado literalmente, carácter a carácter, sem qualquer linguagem de padrões por trás. Isto foi verificado com três padrões correntes — uma âncora de início de linha, uma alternância e uma classe de carateres — e os três devolveram um painel de saída vazio sem mensagem. O comportamento a interiorizar é que aqui uma resposta errada se parece exatamente com uma resposta correta de «nada correspondeu», portanto trate um resultado vazio como uma pergunta e não como um facto: reescreva o termo sem os carateres de sintaxe e veja se aparecem linhas.
Como fico só com as linhas que começam por alguma coisa?
Aqui não pode pedir «início de linha», porque não há âncora. Na prática a versão de subcadeia costuma bastar: filtre pelo código ou prefixo em si, e aceite as linhas que o contenham noutro sítio. Se isso é aceitável depende dos seus dados, e pode descobri-lo barato: filtre uma vez, depois passe o mesmo termo em modo remover e olhe para o que saiu. Se o monte removido não contiver nada que quisesse, a versão frouxa servia. Se precisa mesmo da âncora, um editor de texto com procura por expressão regular é a ferramenta.
O filtro distingue maiúsculas?
Por omissão não. «Ignorar maiúsculas» está ativo ao carregar a página, o contrário da definição por omissão do grep e o contrário do que espera quem usa o terminal a sério. Desligue-o no mesmo painel se precisa da distinção: filtrar uma lista de frutas por apple com o interruptor ativo manteve uma linha APPLE juice, e desligá-lo descartou essa linha mantendo as duas em minúsculas. A dobra é a simples, independente da língua: trata bem as maiúsculas acentuadas mas não faz nada de especial para uma língua concreta.
Porque é que a minha saída filtrada tem buracos?
Porque usou «Remover linhas correspondentes» e o seu texto tinha linhas vazias. Uma linha vazia não contém o seu termo, portanto a ferramenta mantém-na, e ela fica exatamente onde estava — agora rodeada do espaço que as linhas retiradas ocupavam. Passar o remove-blank-lines pelo resultado fecha-as todas de uma vez. Se encadeia vários filtros, faça a limpeza de linhas vazias uma só vez no fim e não a seguir a cada passo, porque cada passagem de remoção abrirá buracos novos.
A ferramenta diz-me quantas linhas corresponderam?
Não é mostrada contagem alguma; obtém as linhas correspondentes e nada mais. Se precisa do número, o caminho mais curto é passar o resultado por um contador de linhas, ou usar o count-occurrences sobre o texto original com o mesmo termo — tendo em conta que conta ocorrências e que uma mesma linha pode conter o seu termo duas vezes, pelo que os dois números podem diferir legitimamente. Se o que quer é a contagem e não as linhas, o count-occurrences é o melhor ponto de partida.

Artigos que podem interessar-lhe

Todos os guias
GuiaLocalizar e substituir: as armadilhas das expressões regulares, demonstradas uma a umaGanancioso contra preguiçoso sobre a mesma cadeia, o ponto que salta as quebras de linha, $& e $$ na substituição, uma regex /g reutilizada que salta uma linha em silêncio, e porque /i nada sabe do i turco. Cada falha executada no Node, com uma rotina contar-e-depois-substituir que as apanha.TutorialNumerar as linhas de um texto para uma revisão a várias mãosA numeração começa em 1 e não pode ser posta a 0, o alinhamento faz-se com espaços e não com zeros, e a ferramenta que os remove desfaz oito dos onze separadores sem mexer na indentação. O que continua sem saber fazer é distinguir os seus números dos dela.ExplicaçãoOs emoji são mais difíceis do que parecem: porque «basta retirá-los» não tem resposta numa linhaUm emoji visível pode valer um ponto de código ou catorze unidades UTF-16. Corremos três expressões regulares populares sobre uma frase real e cada uma falhou de maneira diferente; uma apagou os algarismos. Eis porquê, que propriedade Unicode responde a que pergunta, e a regra de grupos de grafemas que funciona mesmo.ExplicaçãoOnde uma linha pode quebrar: o algoritmo Unicode por trás de cada parágrafo ajustado«Quebrar nos espaços» falha na maioria dos sistemas de escrita. O UAX #14 dá a cada caráter uma classe de quebra de linha; procurámos as nossas no Unicode 17.0.0 e executámos uma implementação conforme sobre espaços inquebráveis, hifenes condicionais, espaços de largura zero, URL, japonês e tailandês.GuiaConverter entre formatos de lista sem perder dados: as regras de aspas que ninguém lêPassar de uma lista com quebras de linha para uma lista com vírgulas é trivial até um item conter uma vírgula. As regras de aspas da RFC 4180, porque um campo CSV pode conter uma quebra de linha, porque as folhas de cálculo europeias usam o ponto e vírgula, e o que um item vazio faz à ida e volta — cada caso executado e impresso.GuiaLimpar uma lista colada de uma folha de cálculo ou de um PDFUma colagem transporta carateres invisíveis: espaços inquebráveis, hífenes condicionais, espaços de largura nula, tabulações e CRLF. Quatro ferramentas de limpeza foram passadas por cada um, e usam três definições diferentes de espaço.

Ferramentas relacionadas

Tudo o que se segue descreve o que estas ferramentas fazem hoje, verificado executando as suas próprias transformações sobre as entradas exatas reproduzidas em cada artigo, e não o que uma norma obrigue uma ferramenta de texto a fazer. O tratamento do texto linha a linha não tem autoridade única: o que conta como espaço, se duas linhas acentuadas são ou não a mesma linha, e onde termina um URL dentro de uma frase são decididos de forma diferente por cada programa onde colar texto. Quando uma ferramenta erra num caso, isso é dito com franqueza em vez de contornado. Antes de passar qualquer disto por uma lista que não possa reexportar, passe por uma cópia e compare o número de linhas nas duas pontas.

Fontes

Detetaste um erro neste artigo?