Nodes/ComfyUI-PhandoNodes/Search by Substring
ComfyUI Node

Search by Substring

A \"Does My Prompt Contain X?\" Node, Without Building a Regex Pipeline

By Phando·Created 2 years ago·Updated 2 years ago· 0
Search by Substring
    • match
    • matchList
    • count
    • found
    textwhole_word
    patterneyes
    defaultnot found

    ComfyUI has no built-in "does this text contain X" check. If you build prompts dynamically - wildcards, tag files, LoRA-triggered words, reusing one caption across steps - you will eventually stare at a blob of text and want to know whether "eyes" is in it. Search by Substring is that question as a node: give it text and a pattern, and it hands back the first match, all matches, a count, and a true/false flag. It's from PhandoNodes, a two-node utility pack that does nothing but string chores (this one plus a text concatenator) and, refreshingly for the ComfyUI ecosystem, has zero dependencies, zero model downloads, and zero setup.

    How it actually works

    The whole thing is about ten lines of stdlib re, and reading them tells you most of what you need. Both the text and the pattern get lowercased first, so matching is case-insensitive - "Eyes" finds "eyes". Then the pattern gets run through encode().decode("unicode_escape"), which is a roundabout way of saying escape sequences like \n work in your pattern. Then it builds a regex:

    regex = rf'\b\w*{pattern}\w*\b'
    

    That means "a whole word containing your substring", not just a bare substring anywhere. Pattern eye matches "eyebrow" and "eyelashes" because they're whole words that contain it. It also means cat matches "location" and "concatenate". Usually that's what you want for tag-style matching; when it's not, it's a gotcha.

    The pattern is also dropped into that regex raw, so regex metacharacters do live: ., [, (, | all behave. But the \b\w*…\w*\b wrapper means anchors like ^ and $ mostly won't do what you expect, and the unescape step eats single backslashes - a literal \d in the widget becomes plain d, so true regex classes need \\d. For everyday substring hunting, just don't put punctuation in the pattern.

    The inputs and outputs that matter

    Three inputs, all plain text:

    • text - the blob to search (multiline). Default is literally the word whole_word, the author's placeholder. Change it.
    • pattern - the substring to look for. Default eyes.
    • default - the fallback string that match outputs when nothing is found. Default not found.

    Four outputs, and they're the useful part:

    • match - the first hit as a STRING, or your default.
    • matchList - every hit as a LIST, so it can feed list-processing nodes.
    • count - an INT. Not just "did it find anything" but how many.
    • found - a BOOLEAN.

    The classic wiring is a text gate: feed found or count into a switch/branching node (Impact Pack and rgthree both have pieces that take a boolean or int input) to steer a conditional path, or use count to scale something like a LoRA strength. match can feed straight back into a prompt node if you're extracting a word to reuse.

    Install

    ComfyUI Manager: search "ComfyUI-PhandoNodes" and install. Or the old-fashioned way:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Phando/ComfyUI-PhandoNodes
    

    Then restart ComfyUI. That's genuinely it - there's no requirements.txt and no heavy dependency in the pyproject, so nothing else to pull. If the node doesn't show up, restart ComfyUI properly and check that the pack folder is in custom_nodes; there's not much else that can go wrong with a pure-Python text node. The one thing that bites people is the defaults: drop the node in untouched and it searches the string whole_word for eyes, returns "not found", and looks broken. It isn't. Type your actual text and pattern.

    The case thing deserves repeating because it's the trap people hit first: everything is lowercased, so match comes back lowercased too, original casing gone. If you need to round-trip the exact original word, this node isn't the one - it's a search tool, not a picker.

    CategoryPhando/Text

    Inputs (3)

    NameTypeDefaultDescription
    textSTRINGwhole_wordSource to be searched
    patternSTRINGeyesSubstring to match (e.g., 'eyes')
    defaultoptSTRINGnot foundFallback value if 'pattern' is not found

    Outputs (4)

    NameTypeDescription
    matchSTRING
    matchListLIST
    countINT
    foundBOOLEAN