String Replace (Multiple)
Eight find-and-replaces, run in order, no regex
- result_text
A prompt arrives from somewhere you don't control - a CivitAI copy-paste, a workflow someone shared, a batch of metadata strings - and it's full of things you want gone. This node does eight of those deletions in one pass.
What it's for
The everyday case in 2026 is inherited boilerplate. A huge share of prompts in circulation still start masterpiece, best quality, ultra detailed, 8k because they were written for SD 1.5 in 2023. On an LLM-encoded model - Z-Image, Flux 2 Klein, Anima - those tokens are inert: the vocabulary was never trained in, and every one of them is a token taken from your description. A/B tested across 20 prompts, the difference was indistinguishable. So the cleaning job is real: strip the fossil vocabulary, strip the score_9, score_8_up stack when you've switched off a Pony model, strip the (concept:1.4) weight syntax when your encoder discards weights or passes them through as literal punctuation.
Doing that by hand every time you paste a new prompt is the kind of chore that makes people stop experimenting. Doing it once, in the graph, means every prompt that flows through gets the same treatment - including the ones you didn't write.
How it works
main_text is a multiline string box, and it's the thing being edited. Then eight pairs: search_1/replace_1 through search_8/replace_8, all single-line. One output, result_text (STRING).
The mechanism is eight sequential str.replace() calls on a running result. That gives you three properties worth knowing:
Order matters, and the output of one feeds the next. If replace_1 inserts a word that search_2 is looking for, search_2 will eat it again. Most of the time that's what you want - chain the general case first, the specific fix second - but it's how people accidentally create loops they then have to hunt.
An empty search is skipped. So you can leave unused pairs blank without consequences, and you cannot use an empty search to mean "insert at position zero." If you need to prepend something, this isn't the tool.
It's literal, not regex. No wildcards, no character classes, no case-insensitivity. To remove masterpiece, you need the exact characters, trailing comma and space included - and if the same word appears mid-prompt without the comma, it survives. Which is usually fine: prompt cleanup is a small number of known strings, and literal replace is honest about that.
The input is cast to a string first, so shoving a non-text value at main_text won't crash - you'll just get its string form. Wire result_text into a CLIP text encode (or into MetaData Append, or a save node's filename field) and that's the whole circuit.
Installing it
ComfyUI-MDSNodes by MarwanDSAI. ComfyUI Manager: search ComfyUI-MDSNodes or MDSNodes, install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/MarwanDSAI/comfyui-mdsnodes
# restart ComfyUI
Nothing to pip install and nothing to download - the repo's requirements.txt is empty and the README states the pack runs on stock ComfyUI dependencies. No model files, no text-processing libraries.
Search String Replace (Multiple); it lives in MDSNodes/text with the key-value selector and the single-replace variant.
Common issues
A replacement appears twice in the output. Your search term appeared twice in the input. str.replace replaces all occurrences, not the first - which surprises people coming from editors that default to one match.
A rule did nothing. Three usual causes: the search text doesn't match exactly (usually a missing or extra space around a comma), a later rule undid it, or the string you're targeting only exists in the model's prompt metadata and not in the text box you're editing. Read the intermediate value with a preview node before adding a ninth rule.
You want to trim whitespace rather than replace text. Different job - the search box is literal, so search_1 = " " and replace_1 = " " will collapse doubles one pass at a time and never fully clean up. Use a dedicated trim node, or the pack's string-trim helper.
It doesn't touch your A1111 weights. Literal replace can't rewrite ((word)) into (word:1.2); you'd need a rule per word, which defeats the point. If you're moving to an encoder without weighting, the correct move is to delete the weights, not translate them.
Not in the node list. Shipped in pack version 1.8.0 (September 2026). Update in Manager, then restart the server - nodes register once, at startup.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| main_text | STRING | The main text block to be modified. | |
| search_1 | STRING | — | |
| replace_1 | STRING | — | |
| search_2 | STRING | — | |
| replace_2 | STRING | — | |
| search_3 | STRING | — | |
| replace_3 | STRING | — | |
| search_4 | STRING | — | |
| replace_4 | STRING | — | |
| search_5 | STRING | — | |
| replace_5 | STRING | — | |
| search_6 | STRING | — | |
| replace_6 | STRING | — | |
| search_7 | STRING | — | |
| replace_7 | STRING | — | |
| search_8 | STRING | — | |
| replace_8 | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| result_text | STRING | The final string after all replacements have been applied. |