re.search (Regex Search)
Find text anywhere in a string and feed the match to other nodes
- flags
- match
You've got a prompt, a filename, a chunk of metadata, and you need to know whether some pattern lives inside it - and, if it does, grab the part that matched. That's re.search, and OvumReSearch is its ComfyUI port. It scans the whole string for the first match anywhere (unlike re.match, which anchors to the start) and hands you back a RE_MATCH object you can pass to the pack's inspector nodes for groups, spans, and everything else.
This is the node I'd tell a beginner to start the regex family with: it's the least surprising of the matchers, and it teaches you the flow that the rest of the suite shares.
How it works
You give it a pattern (multiline field, so multi-line regexes are fine) and a string. It compiles the pattern with the incoming flags, runs pat.search() over every input string, and returns a list of match objects - or None entries where nothing matched, so a no-match never crashes your run. The status readout in the node UI tells you "Matched" or "No match", and for list inputs "Matched 2/5".
Two inputs you'll actually set:
string_in- an optional link. If connected, it overrides thestringwidget and can carry a whole list of strings, which the node processes element-wise. Wire a String Batch / list output in here and you've got a batch search.pos/endpos- optional integers that bound where in the string the search starts and stops. Defaults are the full string (endpos0 means "to the end"). You'll rarely touch these, but they're there for when you're searching inside a slice of a larger text.
The flags input takes a RE_FLAGS value straight from the pack's re.compile flags node (default: IGNORECASE on).
The match output - listed as a list, because the node is list-aware - is the RE_MATCH thing you then feed into re.Match.group to pull out captured groups, re.Match.span for positions, or re.MatchView to see exactly what it found.
Why you'd reach for it
Anything where "does this text contain X" gates a decision. Workflows that parse VHS filenames, read LoRA names out of a prompt, sniff whether a caption contains a trigger word, or route on metadata all start here. Pair it with an IfElse-style node and you can branch on whether a match happened.
Installing it
This ships in comfy-ovum, sfinktah's utility pack. Install via ComfyUI Manager (search "comfy-ovum") or:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
Restart, and it's under ovum/regex. No models needed; dependencies are light pure-Python (Manager handles them; manual installs: pip install -r requirements.txt).
The trap to avoid
People coming from Python expect search vs. match to be interchangeable. They're not: re.search finds the pattern anywhere; re.match only at the start. If your pattern keeps failing on strings that obviously contain it, you grabbed the wrong node - and if it "works too much," remember the default IGNORECASE is on. For "does the whole string conform" you want re.fullmatch instead. But for finding text in the wild, OvumReSearch is the one to reach for.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| pattern | STRING | The regular expression pattern. | |
| string | STRING | The string to search. Used if `string_in` is not connected. | |
| string_inopt | STRING | Input string or list of strings. Overrides `string` widget if connected. | |
| flagsopt | RE_FLAGS | 2 | Regex compilation flags. |
| posopt | INT | 0 | The starting index for the search. |
| endposopt | INT | 0 | The ending index for the search. If 0, searches to the end of the string. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| match | RE_MATCH | — |