Eleven lines, three definitions, nine disagreements
Below are 11 candidate lines, each of which some tool somewhere considers blank. Three
policies pass judgement: the strict length test, the /^\s*$/ pattern that
appears in nearly every snippet, and the one this tool uses. The final column is what the
shipped tool actually does end to end, which is a different question from what its
predicate returns and is therefore checked separately.
| The line contains | Shown | Empty only | JavaScript /^\s*$/ | This tool | Removed by this tool |
|---|---|---|---|---|---|
| Nothing at all Pressing Enter twice. | (empty) | blank | blank | blank | removed |
| One space A stray keystroke, or a trimmed-but-not-quite export. | · | not blank | blank | blank | removed |
| Four spaces Indented code or an outline where the blank line kept its indentation. | ···· | not blank | blank | blank | removed |
| One tab A blank row in TSV data, or an indented editor. | → | not blank | blank | blank | removed |
| Space + tab + space Editing that left a mixture behind; invisible to every human reader. | ·→· | not blank | blank | blank | removed |
| One no-break space A word processor’s empty paragraph, or an HTML that survived a paste. | ⟦NBSP⟧ | not blank | blank | blank | removed |
| One narrow no-break space French typography, and some spreadsheet number formats. | ⟦NNBSP⟧ | not blank | blank | blank | removed |
| One zero-width space Line-break hints inserted by CMSes and chat clients. Occupies no width whatsoever. | ⟦ZWSP⟧ | not blank | not blank | blank | removed |
| One zero-width no-break space (BOM) A byte-order mark that ended up mid-file after two documents were concatenated. | ⟦BOM⟧ | not blank | blank | blank | removed |
| One ideographic space CJK text, where the full-width space is a normal typing key. | not blank | blank | blank | removed | |
| A single full stop Not blank by anyone’s definition — the control row that proves the others. | . | not blank | not blank | not blank | kept |
1 of the 11 is blank under all three definitions: the genuinely empty one. 1 is blank under none: the full stop, which is there as a control so the table has something to be right about. The remaining 9 are disputed — which is to say that whether your blank lines get removed depends entirely on which tool you happened to open.
Two rows are worth pausing on. The no-break space row is the everyday case:
word processors write an empty paragraph as a line holding one U+00A0, and a strict length
test keeps every one of them, which is why "remove blank lines" so often appears to do
nothing to a pasted document. The zero-width space row is the one where
this tool parts company with the standard pattern: /^\s*$/ declares that line
non-blank because JavaScript's \s does not include U+200B. It has no width. It
is blank.
Remove them all, or squeeze the runs?
Two different jobs share one button on most tools. Taking a 7-line sample with 4 blank lines in two runs:
First·paragraph.␊␊␊␊Second·paragraph.␊␊Third·paragraph. | Policy | Result | Lines | Blank lines left |
|---|---|---|---|
| Remove every one | First·paragraph.␊Second·paragraph.␊Third·paragraph. | 3 | 0 |
| Squeeze runs to one | First·paragraph.␊␊Second·paragraph.␊␊Third·paragraph. | 5 | 2 |
Removing every blank line takes 7 lines down to 3 and leaves 0 blank lines, which is what you want for a list that arrived double-spaced. Squeezing takes it to 5 and leaves 2 — the paragraph structure preserved but the four-line gap normalised. Neither is more correct; they are answers to different questions, and the tool asks which one you meant.
Where doubled blank lines come from
- Email quoting. Each round of quoting adds a blank line between paragraphs and a prefix to every line, so a thread that has been forwarded four times is mostly vertical space.
- Copying between line-ending conventions. A CR-terminated file opened in a tool that expects LF shows every line doubled. That is a line-ending problem wearing a blank-line costume — convert the endings instead, or you will strip content.
- Word-processor exports. Empty paragraphs become lines holding one no-break space; a document with generous paragraph spacing becomes a text file with hundreds of them.
- Log and report output. A print statement that already ends its string with a newline, called by a loop that adds another.
The second one is worth checking before you reach for this page at all. If every line is followed by a blank line, the problem is almost certainly the line endings, and removing the blanks will destroy the file rather than fix it. Press Show invisible characters: if you see a CR badge on its own before each LF, that is the diagnosis.
Trailing whitespace, the related nuisance
A line that ends with spaces is not blank, but it causes the same class of trouble: diffs that show changes with nothing visible in them, string comparisons that fail, and markdown that grows an unwanted hard break. The counter under the input reports how many lines end in whitespace — which means a space, a tab or a no-break space, because all three cause the same trouble — and the reveal view shows you which: a faint dot for each ordinary space, a named badge for a tab or an NBSP. Trimming them is the extra-spaces job, not this one — this mode deliberately does not retrim your lines, because a mode that promises to touch only the empty lines should touch only the empty lines.