Skip to content
OneKitly

Filtering Lines by a Pattern Without a Command Line

Published 8/7/2026 · 11 min read · Text & language tools

Daniel Okonkwo

Daniel OkonkwoFront-end developer and tech writer at OneKitly

Web performance · File formats

Checked against 3 sources

View profile
In short

filter-lines splits your text on line breaks, tests each line for a substring, and keeps or drops it. The match is String.prototype.includes on a literal term — there is no regular-expression engine behind the box. Typing ^ERROR into a log returned nothing; so did ERROR|WARN; so did [a-z]+. Each produced an empty output panel with no error message and no note that the pattern had been read literally, which is the one behaviour to know before you start. The opposite is also true and more comforting: an invalid regular expression is harmless here, because it is not a regular expression. Typing a single opening parenthesis matched the line that contains one, exactly as you would want. Ignore case is on by default, so filtering for apple kept the line reading APPLE juice as well as apple pie; grep on a terminal is case-sensitive by default and this tool is not, which is a difference worth holding in mind if you are used to one. Action offers Keep matching lines and Remove matching lines, which correspond to grep and grep -v. Leaving the term empty returns your text unchanged rather than nothing. Two details from the runs: remove mode keeps blank lines, because a blank line does not contain your term, so a filtered log comes back with the gaps where the removed lines were; and all output is joined with plain line feeds, so a Windows file loses its carriage returns on the way through.

This is grep for people who do not use grep, with one important difference: the match is a plain substring, so a real regular expression returns an empty box and no error. Every claim here was checked by running the tool.

What grep does, and which half of it is here

grep reads a text a line at a time, tests each line against a pattern, and writes out the lines that matched. The POSIX specification defines it that way and defines the pattern as a regular expression — a small language in which a caret means start of line, a vertical bar means either, square brackets mean any one of these characters and a plus means one or more of the thing before it. The invert option turns the test around and prints the lines that did not match. The whole idea is about forty years old and it is still the fastest way to answer a question about a log file.

filter-lines implements the loop and the invert option and stops there. The pattern language is not implemented, and importantly it is not partially implemented either: the term you type is compared as a run of characters, whole and unchanged. That is a legitimate design for a box on a web page — most people filtering a list want lines containing the word invoice, not a grammar — but it means the two tools take the same input and give different answers, and the tool that is wrong about it never says so.

The empty box, and why it is empty

Three patterns were run against the same seven-line log. ^ERROR returned nothing, although two lines start with ERROR, because no line contains a literal caret followed by the letters E, R, R, O, R. ERROR|WARN returned nothing, although the log has one of each, because no line contains a literal vertical bar between those two words. [a-z]+ returned nothing, for the same reason: no line contains a square bracket. In every case the output panel was simply empty. Nothing was highlighted, nothing was reported, and nothing suggested that the term had been read differently from the way it was meant.

This is the failure mode that matters, and it is the reverse of the one the phrase invalid regex would suggest. A malformed pattern is the safe case. Typing a single opening parenthesis — which would make a regular-expression engine throw an error about an unterminated group — matched the line containing a parenthesis and returned it. So did a lone full stop, which in the regular-expression language means any character and here means a full stop: on a list containing both a.b and aXb it returned only a.b. If you catch yourself typing regular-expression syntax into this box, the reflex to build is to look at the output and ask whether an empty result is plausible, because the tool will not ask it for you.

Case, accents, and the space you did not mean to type

Ignore case is on out of the box, and it lower-cases both the line and the term before comparing. Filtering a five-line fruit list for apple kept apple pie, APPLE juice and pineapple tart; turning the toggle off dropped APPLE juice and kept the other two. The pineapple line is the reminder that this is a substring test and not a word test: apple is inside pineapple, so the line matches, and there is no whole-word option to stop it. If you need word boundaries, add the surrounding spaces to your term and accept that you will miss the word at the start or end of a line.

Two smaller traps came out of the same runs. A leading space in the term is part of the term: filtering the same list for a space followed by apple returned nothing, because no line has a space before that word in the position tested. And accents follow the rule from the duplicate-line article — a term whose accented letter is written as a letter plus a combining mark matched nothing in a list whose accented letter is a single code point, even though the two look identical in the search box. Both come back to the same discipline: what you typed is compared exactly as typed, including the parts you cannot see.

Remove mode leaves holes

Switch Action to Remove matching lines and the tool drops every line that contains your term and keeps everything else — which includes the blank lines, because a blank line does not contain your term. Run it over a log with an empty line between two entries and the empty line is still there afterwards. It is not a bug, it is the honest reading of the instruction, but the result rarely looks like what people expected, and a filtered file with a dozen orphaned gaps in it is annoying to read. The fix is one more step: run remove-blank-lines over the output.

One more behaviour worth relying on: an empty term returns your text unchanged, not an empty result. That sounds obvious, but the alternative reading — no term, so nothing matches, so nothing comes out — would be equally defensible and would silently blank your input every time you cleared the field to type a new search. The tool takes the safer branch, and it was checked: with the term box empty, all five lines of the test list came back.

What to do when you really do need a pattern

Most pattern questions can be rewritten as substring questions. Lines that start with a code become lines that contain that code, which is looser but usually fine on a log where the code only appears at the start anyway. Either of two words becomes two passes — filter for the first, note the result, filter the original for the second — because there is no alternation. A range of characters generally becomes several passes or a different tool altogether. When the answer really needs a grammar, the honest advice is that a browser text box is the wrong instrument, and the right one is a terminal or a text editor with a regular-expression search.

One caveat about the sibling tool. find-and-replace, on this same site, also takes a literal term — it escapes every character that has a special meaning before building its pattern, which was read in its source and confirmed. So if you were hoping to use it to fake a regular-expression filter, you cannot. The two tools are consistent with each other, which is the good news; neither of them is grep, which is the news you needed before you started.

Terms typed into the Contains box, and what the tool actually returned
Term typedWhat comes backWhy
apple, Ignore case on (the default)apple pie, APPLE juice and pineapple tartBoth sides are lower-cased, and the test is substring, not whole word
apple, Ignore case offapple pie and pineapple tart onlyAPPLE juice no longer contains the exact characters typed
^ERROR on a log whose first two lines start with ERROREmpty output, no error messageNo line contains a literal caret followed by those five letters
ERROR|WARN on the same logEmpty outputThere is no alternation; the vertical bar is just a character to look for
A single opening parenthesisThe line that contains a parenthesis — it worksAn invalid regular expression is the safe case, because none is being compiled
A single full stop, on a list holding a.b and aXba.b onlyThe full stop matches a full stop, not any character
An empty Contains boxThe whole text, unchangedThe tool returns early rather than filtering everything away
Any term, in Remove matching lines mode, on a text with blank linesThe blank lines surviveA blank line does not contain the term, so it is not a match to remove
Filter linesKeep or remove the lines that contain a given word or phrase.Try the tool

Frequently asked questions

Can I use a regular expression in the Contains box?
No. The term is compared literally, character by character, with no pattern language behind it. This was checked on three ordinary patterns — a start-of-line anchor, an alternation and a character class — and all three returned an empty output panel with no message. The behaviour to internalise is that a wrong answer here looks exactly like a correct answer of nothing matched, so treat an empty result as a question rather than a fact: retype the term without its syntax characters and see whether lines appear.
How do I keep only the lines that start with something?
You cannot ask for start of line here, because there is no anchor. In practice the substring version is usually good enough: filter for the code or prefix itself, and accept any line that happens to contain it elsewhere. Whether that is acceptable depends on your data, and you can find out cheaply — filter once, then run the same term through in Remove mode and look at what came out. If the removed pile contains nothing you wanted, the loose version was fine. If you genuinely need the anchor, a text editor with a regular-expression search is the tool for it.
Is the filter case-sensitive?
Not by default. Ignore case is switched on when the page loads, which is the opposite of grep's default and the opposite of what a habitual terminal user expects. Turn it off from the same panel if you need the distinction — filtering a fruit list for apple with the toggle on kept a line reading APPLE juice, and turning it off dropped that line while keeping the two lower-case ones. The folding is the plain language-independent one, so it handles accented capitals correctly but does not do anything special for a particular language.
Why does my filtered output have gaps in it?
Because you used Remove matching lines and your text had blank lines in it. A blank line does not contain your term, so the tool keeps it, and it stays exactly where it was — now surrounded by the space the removed lines used to occupy. Running remove-blank-lines over the result closes them all in one pass. If you are chaining several filters, do the blank-line cleanup once at the end rather than after each step, because each Remove pass will open new gaps.
Does the tool tell me how many lines matched?
No count is shown; you get the matching lines and nothing else. If you need the number, the shortest path is to run the result through a line counter, or to use count-occurrences on the original text with the same term — bearing in mind that it counts occurrences and a single line may contain your term twice, so the two numbers can legitimately differ. If the count is what you actually want and the lines are not, count-occurrences is the better starting point.

Articles you may find interesting

All guides
GuideFind and Replace: The Regex Features That Bite, Demonstrated One by OneGreedy against lazy on the same string, the dot that skips newlines, $& and $$ in the replacement, a reused /g regex that silently skips a row, and why /i knows nothing about Turkish i. Every failure run in Node, with a count-then-replace routine that catches them.How-toNumbering the Lines of a Text for a Review with Several PeopleNumbering starts at 1 and cannot be set to 0, the alignment is spaces rather than zeros, and the remover undoes eight of the eleven separators without touching the indentation. What it still cannot do is tell your numbers from its own.ExplainerEmoji Are Harder Than They Look: Why "Just Strip the Emoji" Has No One-Line AnswerOne visible emoji can be one code point or fourteen UTF-16 units. We ran three popular regexes against a real sentence and each broke differently — one deleted the digits. Here is why, which Unicode property answers which question, and the grapheme-cluster rule that actually works.ExplainerWhere a Line May Break: The Unicode Algorithm Behind Every Wrapped Paragraph"Break at spaces" fails in most of the world's writing systems. UAX #14 gives every character a line-break class; we looked ours up in Unicode 17.0.0 and ran a conforming implementation over no-break spaces, soft hyphens, zero-width spaces, URLs, Japanese and Thai.GuideConverting Between List Formats Without Losing Data: The Quoting Rules Nobody ReadsTurning a newline list into a comma list is trivial until an item contains a comma. RFC 4180's quoting rules, why a CSV field may contain a newline, why European spreadsheets use the semicolon, and what an empty item does to a round trip — every case run and printed.GuideCleaning Up a List Pasted from a Spreadsheet or a PDFA paste carries characters you cannot see: no-break spaces, soft hyphens, zero-width spaces, tabs and CRLF. Four cleanup tools were run against each of them, and they use three different definitions of whitespace.

Related tools

Everything here describes what these tools do today, checked by running their own transforms against the exact inputs printed in each article, not what a standard obliges a text tool to do. Line-level text handling has no single authority: what counts as whitespace, whether two accented lines are the same line, and where a URL ends in running prose are decided differently by every program you will ever paste into. Where a tool gets a case wrong, that is said plainly rather than worked around. Before you run any of this over a list you cannot re-export, run it over a copy and compare the line count at both ends.

Sources

Spotted a mistake in this article?