文本批量替换
Swap a whole glossary of names — without touching the dialogue
- text
Two things make text replacement in a prompt pipeline annoying. The first is doing twenty substitutions without stacking twenty nodes. The second is the one that actually hurts: you rename a character, run a replace, and everything downstream is fine - except you've also rewritten the character's dialogue, because their name appears inside quoted lines.
文本批量替换 (YanhuoTextReplace) handles both, and the second one is why it's worth having.
Line-paired batching
The node takes text, plus 查找文本 and 替换文本, both multiline. Line n of the find list pairs with line n of the replace list, so one node does a whole glossary:
find: 小明
小李
旧城
replace: 陈默
林昭
临港新区
Empty find lines are skipped, so you can leave gaps without breaking alignment. And before anything is applied, the pairs are sorted by find-string length, longest first. That ordering is the entire reason the output isn't garbage: replacing 小明 before 小明明 would leave a half-mangled 小明-plus-明 behind, and no amount of careful ordering in your head survives an edit six weeks from now. Longest-first is just correct, and it's baked in.
The output is a single text STRING - clean to chain into another replace node or straight into a CLIP text encode.
台词开关: the quote-protection mask
The feature this node is really built around. Turn 台词开关 on and text inside quotes is exempt from replacement. The console/README calls it 台词保护 ("dialogue protection"), and it covers six quote styles: plain "..." and '...', curly “...” and ‘...’, and the CJK corner brackets 「...」 and 『...』.
It's implemented as a protection mask built by pairing opening quotes with their matching closer - same-type pairing only, so a 「 won't get closed by a ”. The mask includes the quote characters themselves. Then each find string is matched positionally: if any character of the match falls inside a protected span, that occurrence is skipped entirely rather than partially replaced. You get no half-substitutions at a boundary, which is the right call.
Two consequences worth knowing:
- Unclosed quotes don't swallow the file. An opening quote that never closes stays unmatched and gets treated as ordinary text, so a typo'd quote leaves the rest replaceable instead of protecting everything after it.
- The protection is structural, not semantic. It doesn't know which quotes are dialogue and which are a character quoting a title inside narration. It protects everything bracketed. For a script that's usually exactly what you want; for text with heavy use of quotes as emphasis, it will protect things you meant to change.
Also note the mask is rebuilt against the current text on each pass, which matters because replacements can shift the positions of everything after them.
Typical uses
Renaming a character across a script you're about to feed to a TTS or a storyboard pipeline, with dialogue preserved so a voice-clip pass still matches. Swapping localisation terms - 中文 names to English transliterations - across a prompt library. Stripping out boilerplate descriptions that a shared workflow or recipe injects, without it touching quoted example text.
And on the defensive side: run it before anything that encodes, so the fix lands on the source text rather than on four separate encoded copies.
Install
One of 16 nodes in yanhuo-easy-use - category yanhuo, Chinese labels in the canvas, MIT, v1.3.1. ComfyUI Manager → search the pack title, install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/yanhuoxunxianren/yanhuo-easy-use
# restart ComfyUI
No pip install: the pack's pyproject.toml declares no dependencies, and there's nothing to download. This node is pure string manipulation - no models, no GPU, works on a machine with neither.
Common issues
"It replaced something inside my dialogue." Either 台词开关 is off, or the quotes around that line aren't one of the six recognized styles - a stray mismatched close won't close its span, and the text inside becomes ordinary text.
"It replaced nothing in a big block." Look for an unclosed or mispaired quote. If a span did get protected, the region between the quotes is off-limits, and if you meant to edit inside it, the honest fix is to remove the protection toggle and make the find strings specific enough that the longest-first ordering handles the rest.
"A short name got mangled inside a longer one." That can't happen within one node - pairs are sorted longest-first. But if you have two nodes chained, the second sees the output of the first, so order those by how specific they are.
"My find and replace lists drifted out of sync." Nothing validates the pairing. A blank line in the middle of 查找文本 shifts everything after it. Keep the two boxes visually aligned.
"Only the first occurrence changed on each line." The opposite - all occurrences are replaced. If you're converting a name to something that itself contains the find string, you've built an infinite-ish loop by accident; the node won't notice, but the output will be a mess.
"Case." There's no case-insensitive matching. Provide both spellings as separate pairs.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | 输入要进行替换操作的原始文本。 | |
| 查找文本 | STRING | 要查找的文本列表,每行对应一组。 第1行对应替换文本第1行,第2行对应替换文本第2行,以此类推。 | |
| 替换文本 | STRING | 要替换的文本列表,每行对应一组。 第1行对应查找文本第1行,第2行对应查找文本第2行,以此类推。 | |
| 台词开关 | BOOLEAN | false | 【台词保护】 开启后,被以下引号包裹的「人物说话内容」不进行替换,原文保留: ● 半角双引号 / 单引号:"..." '...' ● 中文弯引号:“...” ‘...’ ● 中文直角引号:「...」 『...』 关闭时,整段文本正常执行批量替换。 |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |