Nodes/Comfy Text Stats/Text -> Character Search Replace
ComfyUI Node

Text -> Character Search Replace

Fix mangled quotes and dashes before they reach your prompt

By scofano·Created 11 months ago·Updated 3 months ago· 3
Text -> Character Search Replace
    • processed_text
    text
    replacements“|" ”|" „|" «|" »|" ‘|' ’|' ‚|' ´|' `|' –|- —|, −|- ‐|- ‑|- •|- ·|- *|  |_ …|...

    Copy text out of a Word doc, a web page, or a chat app and the curly quotes and em dashes come along for the ride. Fine for humans, occasionally annoying for a text encoder - and if you're captioning a dataset or building prompts, you probably want them normalized before they land anywhere. That's what this node does: a rule-based search-and-replace list you edit directly on the widget. It's part of the Comfy Text Stats pack from scofano, pure Python, zero dependencies.

    How the replacement list works

    The replacements input is multiline text, one rule per line, using search|replacement as the separator. Everything before the first | is the search string - and it can be multiple characters, so ,10|, rewrites ,10 back to , - and everything after is the replacement. An empty replacement deletes the match. Lines without a | are silently skipped, and leading/trailing spaces are meaningful, so don't "tidy" the list up too aggressively.

    Rules apply in order, top to bottom, with Python's str.replace() - every occurrence, not just the first. That ordering matters: a later rule can re-edit what an earlier one produced, so treat the list like a pipeline.

    The defaults are a starting point, not a contract

    The node ships with a list that handles the usual suspects: curly quotes to straight, en and em dashes to hyphens, ellipsis to ..., bullets to -. Two entries are opinionated enough that you should glance at them before trusting the output. The em dash default maps to , - comma-space, not a hyphen - which reads like a style choice and will surprise you the first time. And there's a line mapping non-breaking space to underscore, which only makes sense if you specifically want that.

    Inputs and output

    Two inputs: text (multiline) and replacements (multiline, prefilled with that default list). One output: processed_text, the fully-mapped result. It's a STRING, so it plugs straight into your CLIP text encoder, a caption combiner, or anywhere the raw text was going. That's the whole shape of the node.

    Installing it

    It's in the Comfy Text Stats pack, so you get the whole set in one go. ComfyUI Manager is easiest: Manager → Custom Nodes Manager → search "Comfy Text Stats" → Install, then restart ComfyUI. Or clone it yourself:

    cd ComfyUI/custom_nodes
    git clone https://github.com/scofano/comfy-text-stats
    

    Restart after. No extra dependencies - the pack's requirements file is literally a comment saying "no external dependencies required" - and nothing to download.

    Where people get burned

    • An empty search string is dropped, so a rule like |x does nothing.
    • These are dumb, plain string replacements, not regex. If you're used to regex power, this is the simpler, more predictable cousin - and you can't do lookarounds or alternation in it.
    • Because rules run in sequence, test on a couple of sample lines before trusting it in a batch pipeline. The input length is what drives its change detection, so edited rules recompute cleanly.
    CategoryText/Utils

    Inputs (2)

    NameTypeDefaultDescription
    textSTRING
    replacementsSTRING“|" ”|" „|" «|" »|" ‘|' ’|' ‚|' ´|' `|' –|- —|, −|- ‐|- ‑|- •|- ·|- *|  |_ …|...

    Outputs (1)

    NameTypeDescription
    processed_textSTRING