Vai al contenuto
OneKitly

Filtrare righe secondo uno schema, senza riga di comando

Pubblicato il 07/08/2026 · 11 min di lettura · Strumenti testo e lingua

Daniel Okonkwo

Daniel OkonkwoSviluppatore front-end e redattore Tech presso OneKitly

Performance web · Formati di file

Verificato su 3 fonti

Vedi il profilo
In breve

filter-lines divide il tuo testo sulle interruzioni di riga, verifica in ogni riga la presenza di una sottostringa, e la tiene o la scarta. Il confronto è un includes di stringa su un termine letterale: dietro il riquadro non c'è alcun motore di espressioni regolari. Digitare ^ERROR in un log non ha restituito nulla; ERROR|WARN nemmeno; [a-z]+ nemmeno. Ciascuno ha prodotto un pannello di uscita vuoto, senza messaggio d'errore e senza avviso che lo schema fosse stato letto alla lettera, ed è questo il comportamento da conoscere prima di cominciare. Vale anche il contrario, ed è più rassicurante: un'espressione regolare non valida qui è innocua, perché non è un'espressione regolare. Digitare una semplice parentesi aperta ha tenuto la riga che ne contiene una, esattamente come vorresti. «Ignora maiuscole» è attivo di default: filtrare per apple ha tenuto la riga APPLE juice tanto quanto apple pie; grep in un terminale distingue le maiuscole di default e questo strumento no, differenza da tenere a mente se sei abituato a uno dei due. L'azione offre «Mantieni le corrispondenze» e «Rimuovi le corrispondenze», che corrispondono a grep e grep -v. Lasciare il termine vuoto restituisce il tuo testo immutato, non nulla. Due dettagli dalle prove: la modalità rimuovi conserva le righe vuote, perché una riga vuota non contiene il tuo termine, quindi un log filtrato torna con i buchi lasciati dalle righe tolte; e tutto l'output è riunito con semplici avanzamenti riga, così un file Windows perde i ritorni a capo per strada.

Questo è grep per chi non usa grep, con una differenza importante: la ricerca è una sottostringa letterale, quindi una vera espressione regolare restituisce un riquadro vuoto e nessun errore. Ogni affermazione è stata verificata eseguendo lo strumento.

Cosa fa grep, e quale metà si trova qui

grep legge un testo una riga alla volta, confronta ogni riga con uno schema e scrive le righe che corrispondono. La specifica POSIX lo definisce così e definisce lo schema come un'espressione regolare: un piccolo linguaggio in cui un accento circonflesso significa «inizio riga», una barra verticale «oppure», le parentesi quadre «uno qualsiasi di questi caratteri» e un più «una o più volte ciò che precede». L'opzione di inversione capovolge il test e stampa le righe che non corrispondono. L'idea ha una quarantina d'anni ed è ancora il modo più rapido per rispondere a una domanda su un file di log.

filter-lines implementa il ciclo e l'opzione di inversione, e si ferma lì. Il linguaggio degli schemi non è implementato, e soprattutto non lo è a metà: il termine che digiti viene confrontato come una sequenza di caratteri, intera e immutata. È un progetto legittimo per un riquadro su una pagina web — la maggior parte di chi filtra un elenco vuole le righe che contengono la parola fattura, non una grammatica — ma significa che i due strumenti prendono lo stesso input e danno risposte diverse, e quello che sbaglia non lo dice mai.

Il riquadro vuoto, e perché è vuoto

Tre schemi sono stati eseguiti sullo stesso log di sette righe. ^ERROR non ha restituito nulla, benché due righe inizino con ERROR, perché nessuna riga contiene un accento circonflesso letterale seguito dalle lettere E, R, R, O, R. ERROR|WARN non ha restituito nulla, benché il log ne abbia uno per tipo, perché nessuna riga contiene una barra verticale letterale fra quelle due parole. [a-z]+ non ha restituito nulla, per lo stesso motivo: nessuna riga contiene una parentesi quadra. In ogni caso il pannello di uscita era semplicemente vuoto. Nulla è stato evidenziato, nulla segnalato, e nulla ha suggerito che il termine fosse stato letto diversamente da come lo si intendeva.

È questo il modo di fallimento che conta, ed è l'opposto di ciò che l'espressione «regex non valida» suggerirebbe. Uno schema malformato è il caso sicuro. Digitare una semplice parentesi aperta — cosa che farebbe lanciare a un motore di espressioni regolari un errore di gruppo non chiuso — ha tenuto la riga che contiene una parentesi e l'ha restituita. Lo stesso per un punto isolato, che nel linguaggio delle espressioni regolari significa «qualsiasi carattere» e qui significa «un punto»: su un elenco con a.b e aXb ha restituito solo a.b. Se ti sorprendi a digitare sintassi di espressione regolare in questo riquadro, il riflesso da costruire è guardare l'output e chiederti se un risultato vuoto sia plausibile, perché lo strumento non se lo chiederà per te.

Maiuscole, accenti e lo spazio che non volevi digitare

«Ignora maiuscole» è attivo di fabbrica e mette in minuscolo sia la riga sia il termine prima di confrontare. Filtrare un elenco di cinque frutti per apple ha tenuto apple pie, APPLE juice e pineapple tart; spegnere l'interruttore ha scartato APPLE juice e tenuto le altre due. La riga di pineapple ricorda che questo è un test di sottostringa e non di parola: apple sta dentro pineapple, quindi la riga corrisponde, e non c'è opzione «parola intera» che lo impedisca. Se ti servono confini di parola, aggiungi gli spazi attorno al tuo termine e accetta che ti sfuggirà la parola a inizio o fine riga.

Dalle stesse prove sono uscite due trappole minori. Uno spazio iniziale nel termine fa parte del termine: filtrare lo stesso elenco per «spazio più apple» non ha restituito nulla, perché nessuna riga ha uno spazio davanti a quella parola nella posizione provata. E gli accenti seguono la regola dell'articolo sui duplicati: un termine la cui lettera accentata è scritta come lettera più segno combinante non ha trovato nulla in un elenco la cui lettera accentata è un solo punto di codice, benché le due sembrino identiche nel campo di ricerca. Entrambe tornano alla stessa disciplina: ciò che hai digitato viene confrontato esattamente come l'hai digitato, comprese le parti che non vedi.

La modalità rimuovi lascia buchi

Porta l'azione su «Rimuovi le corrispondenze» e lo strumento scarta ogni riga che contiene il tuo termine e tiene tutto il resto — comprese le righe vuote, perché una riga vuota non contiene il tuo termine. Eseguilo su un log con una riga vuota fra due voci e la riga vuota è ancora lì dopo. Non è un bug, è la lettura onesta dell'istruzione, ma il risultato somiglia di rado a quel che ci si aspettava, e un file filtrato con una dozzina di buchi orfani è fastidioso da leggere. Il rimedio è un passaggio in più: esegui remove-blank-lines sull'output.

Un altro comportamento su cui contare: un termine vuoto restituisce il tuo testo immutato, non un risultato vuoto. Sembra ovvio, ma la lettura opposta — nessun termine, quindi nulla corrisponde, quindi nulla esce — sarebbe altrettanto difendibile e svuoterebbe in silenzio il tuo input ogni volta che cancelli il campo per digitare una nuova ricerca. Lo strumento sceglie il ramo più sicuro, ed è stato verificato: con il campo vuoto sono tornate tutte e cinque le righe dell'elenco di prova.

Cosa fare quando ti serve davvero uno schema

La maggior parte delle domande di schema si può riscrivere come domanda di sottostringa. «Righe che iniziano con un codice» diventa «righe che contengono quel codice», più lasco ma di solito sufficiente su un log dove il codice compare comunque solo all'inizio. «Una qualsiasi di due parole» diventa due passate — filtra per la prima, annota il risultato, filtra l'originale per la seconda — perché non c'è alternanza. «Un intervallo di caratteri» diventa in genere più passate, o direttamente un altro strumento. Quando la risposta ha davvero bisogno di una grammatica, il consiglio onesto è che un riquadro di testo in un browser è lo strumento sbagliato, e quello giusto è un terminale o un editor di testo con ricerca per espressione regolare.

Un'avvertenza sullo strumento gemello. find-and-replace, su questo stesso sito, prende anch'esso un termine letterale: fa l'escape di ogni carattere con significato speciale prima di costruire il suo schema, cosa letta nel codice e confermata. Quindi se speravi di usarlo per simulare un filtro a espressione regolare, non puoi. I due strumenti sono coerenti fra loro, questa è la buona notizia; nessuno dei due è grep, questa è la notizia che ti serviva prima di cominciare.

Termini digitati nel campo «Contiene», e cosa lo strumento ha davvero restituito
Termine digitatoCosa tornaPerché
apple, «Ignora maiuscole» attivo (predefinito)apple pie, APPLE juice e pineapple tartEntrambi i lati sono messi in minuscolo, e il test è di sottostringa, non di parola intera
apple, «Ignora maiuscole» spentosolo apple pie e pineapple tartAPPLE juice non contiene più i caratteri esatti digitati
^ERROR su un log le cui prime due righe iniziano con ERROROutput vuoto, nessun messaggio d'erroreNessuna riga contiene un accento circonflesso letterale seguito da quelle cinque lettere
ERROR|WARN sullo stesso logOutput vuotoNon c'è alternanza; la barra verticale è solo un carattere da cercare
Una semplice parentesi apertaLa riga che contiene una parentesi — funzionaUn'espressione regolare non valida è il caso sicuro, perché nessuna viene compilata
Un punto isolato, su un elenco con a.b e aXbsolo a.bIl punto corrisponde a un punto, non a un carattere qualsiasi
Un campo «Contiene» vuotoIl testo intero, immutatoLo strumento esce subito invece di filtrare via tutto
Qualsiasi termine, in modalità «Rimuovi le corrispondenze», su un testo con righe vuoteLe righe vuote sopravvivonoUna riga vuota non contiene il termine, quindi non è una corrispondenza da rimuovere
Filtra righeMantieni o rimuovi le righe che contengono una parola o frase.Prova lo strumento

Domande frequenti

Posso usare un'espressione regolare nel campo «Contiene»?
No. Il termine viene confrontato alla lettera, carattere per carattere, senza alcun linguaggio di schemi dietro. È stato verificato su tre schemi ordinari — un'ancora di inizio riga, un'alternanza e una classe di caratteri — e tutti e tre hanno restituito un pannello di uscita vuoto senza messaggio. Il comportamento da interiorizzare è che qui una risposta sbagliata assomiglia esattamente a una risposta corretta di «nulla ha corrisposto», quindi tratta un risultato vuoto come una domanda e non come un fatto: ridigita il termine senza i caratteri di sintassi e guarda se compaiono righe.
Come tengo solo le righe che iniziano con qualcosa?
Qui non puoi chiedere «inizio riga», perché non c'è ancora. In pratica la versione a sottostringa di solito basta: filtra per il codice o prefisso stesso, e accetta le righe che lo contengono altrove. Se ciò sia accettabile dipende dai tuoi dati, e puoi scoprirlo a poco prezzo — filtra una volta, poi passa lo stesso termine in modalità rimuovi e guarda cosa è uscito. Se il mucchio rimosso non contiene nulla che volevi, la versione lasca andava bene. Se ti serve davvero l'ancora, un editor di testo con ricerca per espressione regolare è lo strumento adatto.
Il filtro distingue maiuscole e minuscole?
Di default no. «Ignora maiuscole» è attivo al caricamento della pagina, l'opposto dell'impostazione predefinita di grep e l'opposto di ciò che si aspetta chi usa abitualmente il terminale. Spegnilo dallo stesso pannello se ti serve la distinzione: filtrare un elenco di frutti per apple con l'interruttore attivo ha tenuto una riga APPLE juice, e spegnerlo ha scartato quella riga tenendo le due minuscole. Il ripiegamento è quello semplice, indipendente dalla lingua: tratta correttamente le maiuscole accentate ma non fa nulla di speciale per una lingua particolare.
Perché il mio output filtrato ha dei buchi?
Perché hai usato «Rimuovi le corrispondenze» e il tuo testo aveva righe vuote. Una riga vuota non contiene il tuo termine, quindi lo strumento la tiene, e resta esattamente dov'era — ora circondata dallo spazio che le righe rimosse occupavano. Eseguire remove-blank-lines sul risultato le chiude tutte in una passata. Se concateni più filtri, fai la pulizia delle righe vuote una sola volta alla fine e non dopo ogni passaggio, perché ogni passata di rimozione aprirà nuovi buchi.
Lo strumento mi dice quante righe hanno corrisposto?
Non viene mostrato alcun conteggio; ottieni le righe corrispondenti e nient'altro. Se ti serve il numero, la via più breve è passare il risultato in un contatore di righe, oppure usare count-occurrences sul testo originale con lo stesso termine — tenendo presente che conta le occorrenze e che una stessa riga può contenere il tuo termine due volte, per cui i due numeri possono legittimamente differire. Se ciò che vuoi è il conteggio e non le righe, count-occurrences è il punto di partenza migliore.

Articoli che potrebbero interessarti

Tutte le guide
GuidaTrova e sostituisci: le trappole delle espressioni regolari, dimostrate una per unaGoloso contro pigro sulla stessa stringa, il punto che salta gli a capo, $& e $$ nella sostituzione, una regex /g riusata che salta una riga in silenzio, e perché /i non sa nulla della i turca. Ogni guasto eseguito in Node, con una routine conta-poi-sostituisci che li intercetta.TutorialNumerare le righe di un testo per una revisione a più maniLa numerazione parte da 1 e non si può impostare a 0, l'allineamento usa spazi e non zeri, e lo strumento che li toglie annulla otto degli undici separatori senza toccare l'indentazione. Quello che ancora non sa fare è distinguere i tuoi numeri dai suoi.SpiegazioneLe emoji sono più difficili di quanto sembri: perché «basta toglierle» non ha una risposta in una rigaUna emoji visibile può valere un punto di codice o quattordici unità UTF-16. Abbiamo lanciato tre espressioni regolari diffuse su una frase vera e ognuna si è rotta in modo diverso; una ha cancellato le cifre. Ecco perché, quale proprietà Unicode risponde a quale domanda, e la regola a gruppi di grafemi che funziona davvero.SpiegazioneDove una riga può andare a capo: l'algoritmo Unicode dietro ogni paragrafo mandato a capo«Andare a capo sugli spazi» fallisce nella maggior parte dei sistemi di scrittura. UAX #14 assegna a ogni carattere una classe di interruzione di riga; abbiamo cercato le nostre in Unicode 17.0.0 ed eseguito un'implementazione conforme su spazi unificatori, trattini morbidi, spazi a larghezza zero, URL, giapponese e thai.GuidaConvertire fra formati di elenco senza perdere dati: le regole di virgolettatura che nessuno leggeTrasformare un elenco a capo in un elenco a virgole è banale finché un elemento non contiene una virgola. Le regole di virgolettatura della RFC 4180, perché un campo CSV può contenere un a capo, perché i fogli di calcolo europei usano il punto e virgola, e cosa fa un elemento vuoto all'andata e ritorno — ogni caso eseguito e stampato.GuidaPulire un elenco incollato da un foglio di calcolo o da un PDFUn incolla porta con sé caratteri invisibili: spazi unificatori, trattini morbidi, spazi a larghezza zero, tabulazioni e CRLF. Quattro strumenti di pulizia sono stati eseguiti su ciascuno, e usano tre definizioni diverse di spazio.

Strumenti correlati

Tutto quanto segue descrive ciò che questi strumenti fanno oggi, verificato eseguendo le loro stesse trasformazioni sugli input esatti riportati in ogni articolo, e non ciò che una norma imponga a uno strumento di testo. Il trattamento del testo riga per riga non ha un'autorità unica: cosa conta come spazio, se due righe accentate siano o no la stessa riga, e dove finisca un URL dentro una frase sono decisi in modo diverso da ogni programma in cui incollerai del testo. Quando uno strumento sbaglia un caso, lo si dice apertamente invece di aggirarlo. Prima di passare qualsiasi cosa di questo su un elenco che non potrai riesportare, passa su una copia e confronta il numero di righe alle due estremità.

Fonti

Hai notato un errore in questo articolo?