JavaScript正则表达式中嵌套树结构的重复模式匹配问题咨询
Hey Rodrigo! Let's fix those regex patterns so they properly validate your nested tree structure strings. The key issue with your current attempts is that you aren't using grouped subpatterns to repeat the "node + dot" sequence, plus you're missing start/end anchors (^/$) to ensure you match the entire string (not just a part of it).
Step 1: Break Down the Exact Rules
Let's restate your requirements clearly to cover every edge case:
- Must start with a single
$(no$$allowed) - Nodes are
\w{1,32}(1-32 word characters), separated by single dots (no consecutive dots, no empty nodes like$.foo) - Optional leaf node is separated by
->, and also must be\w{1,32} - Valid structures fall into 3 categories:
- Multi-node chain (no leaf):
$node1.node2.nodeN - Single root + leaf:
$node->leaf - Multi-node chain + leaf:
$node1.node2.nodeN->leaf
- Multi-node chain (no leaf):
- Invalid cases include: single node with no dots/leaf, consecutive dots, empty nodes, leading
$$
Step 2: The Correct Regex Patterns
We can split this into targeted patterns for with/without leaf nodes, or combine into one all-encompassing regex. Let's cover both options:
Pattern 1: Match strings without a leaf node
This ensures we have at least two nodes separated by single dots:
const noLeafRegex = /^\$\w{1,32}(\.\w{1,32})+$/;
^= anchor to start of string\$= match the required single dollar sign\w{1,32}= first valid node (1-32 word characters)(\.\w{1,32})+= repeat the "single dot + valid node" subpattern at least once (guarantees multiple nodes)$= anchor to end of string
Pattern 2: Match strings with a leaf node
This allows either a single root node or multi-node chain before the -> leaf:
const withLeafRegex = /^\$\w{1,32}(\.\w{1,32})*->\w{1,32}$/;
(\.\w{1,32})*= repeat the "dot + node" subpattern 0 or more times (so single root nodes are allowed)->\w{1,32}= match the leaf separator and valid leaf node
Combined Pattern (match all valid cases)
If you want one regex to cover every valid structure:
const combinedRegex = /^(?:\$\w{1,32}(\.\w{1,32})+|\$\w{1,32}->\w{1,32}|\$\w{1,32}(\.\w{1,32})+->\w{1,32})$/;
(?:...)= non-capturing group (groups the three valid cases without storing unnecessary capture data)- The three branches cover: multi-node no leaf, single node + leaf, multi-node + leaf
Step 3: Test Against Your Examples
Let's verify these patterns work with your test cases:
Valid Examples
$root.f1.f2->col4: MatcheswithLeafRegexand the third branch ofcombinedRegex✅$f4.folder7: MatchesnoLeafRegexand first branch ofcombinedRegex✅$f1->col7: MatcheswithLeafRegexand second branch ofcombinedRegex✅
Invalid Examples
$root.g5.tt.dd...bbh.hht.sdwswsw->col7: Consecutive dots break the(\.\w{1,32})pattern (needs a valid node after each dot) ❌$.ferf->45: No valid node after$(starts with.), fails all patterns ❌$$e.fe.45: Starts with$$(our regex expects only one$at the start) ❌$feefefefefefefefe: No dots or->, doesn't match any branch ❌
Key Concept: Repeating Subpatterns
Your original issue was that quantifiers like + only repeat the immediately preceding token. To repeat an entire subpattern (like "dot + node"), you wrap it in parentheses:
- Wrong:
\w+\.+→ repeats the.character only - Correct:
(\.\w{1,32})+→ repeats the entire ".+ valid node" sequence
Also, always use ^ and $ to anchor your regex to the start/end of the string—otherwise you might accidentally match valid parts of an invalid string (like $$e.fe.45 would have a partial match for $e.fe.45 if you skip anchors).
内容的提问来源于stack exchange,提问作者Rodrigo Belli

