I draw a bar for every sentence to find the ones that run too long

2026-11-11来源 dev.toEnglish

Most of my editing notes to myself used to say the same thing: "this paragraph feels heavy." It took me a while to work out why. Usually the words were fine. The problem was rhythm. Either one sentence ran on for forty words and lost the reader halfway, or five sentences in a row had exactly the same length and the paragraph started to drone.

Both problems are hard to see while reading for meaning, because I'm following the argument, not counting. So I stopped trying to see them and wrote a small script that draws them for me.

What the script shows

It reads a Markdown file, splits it into paragraphs and sentences, and prints one bar per sentence. The length of the bar is the number of words. Any sentence over a limit gets flagged with its first few words, so I can find it in the draft.

The output for one paragraph looks like this:

Paragraph 4 9 ######### 14 ############## 38 ###################################### <- When the client sends their notes back a... 6 ###### 

That 38 jumps out immediately.

The script

import re import sys from pathlib import Path FENCE = "`" * 3 LIST_ITEM = re.compile(r"([-*+]|\d+\.)\s") LIMIT = int(sys.argv[2]) if len(sys.argv) > 2 else 30 def paragraphs(text): in_code = False current = [] for line in text.splitlines(): stripped = line.strip() if stripped.startswith(FENCE): in_code = not in_code continue if in_code or stripped.startswith("#"): continue if LIST_ITEM.match(stripped): if current: yield " ".join(current) current = [stripped] elif stripped: current.append(stripped) elif current: yield " ".join(current) current = [] if current: yield " ".join(current) text = Path(sys.argv[1]).read_text(encoding="utf-8") for number, para in enumerate(paragraphs(text), start=1): print(f"Paragraph {number}") for sentence in re.split(r"(?<=[.!?])\s+", para): words = len(sentence.split()) line = f" {words:3d} {'#' * words}" if words > LIMIT: line += f" <- {sentence[:40]}..." print(line) 

A few notes on how it works:

  • It skips fenced code blocks and headings, because those aren't prose and would only add noise. The fence marker is built from three backtick characters at runtime, so the script itself contains no literal fence that could confuse a Markdown renderer when I paste it into a post.
  • Each list item counts as its own paragraph. Bullet points often have no full stop, and without this rule a whole list gets measured as one enormous sentence.
  • Sentences are split after ., ! or ? followed by a space. That's crude. Abbreviations like "e.g." will create a false break now and then, which I can live with because I'm looking for patterns, not exact numbers.
  • The limit is 30 words by default. You can pass a different one as the second argument.

Running it

python3 sentence_map.py draft.md python3 sentence_map.py draft.md 25 

I run it once a draft is complete, never while I'm still writing. During a first draft I want long, messy sentences. Fixing rhythm too early just slows me down.

What I look for in the bars

Single spikes. A bar much longer than its neighbours is almost always two or three ideas joined with "and", "which" or a dash. I split it at the first natural break and read both halves out of context to check they still make sense.

Flat blocks. Four or five bars of nearly identical length are the drone I mentioned. The fix is not to make everything short. It's to vary: let one sentence run a bit, then follow it with a short one. Like this.

Short bars everywhere. This surprised me. When I'm tired, I overcorrect and write in choppy fragments. A page of bars under eight words reads like a list of instructions, even when it isn't one. Joining two related sentences often makes the paragraph sound more human.

What it won't tell you

The script counts words, nothing more. A 35-word sentence can be perfectly clear if it's a simple list, and a 12-word sentence can be impossible to parse. So I treat every flag as a question, not an error: is this sentence long because it needs to be, or because I didn't decide where it ends?

I also don't chase an average. There's no correct sentence length for the web, and a draft where every sentence is 15 words would be just as tiring as one full of 40-word sentences. What I want is variety, with the longest sentences reserved for places where the reader already has the context to follow them.

Running the script and fixing the worst spikes takes me a few minutes, and the paragraphs that used to feel heavy now usually just feel normal.

原文:https://www.a8q9.cn/en/article/i-draw-a-bar-for-every-sentence-to-find-the-ones-that-run-too-long-7a98e8.html

相关文章