JavaScript正则表达式行为异常:Discord Bot脚本语言开发遇阻
Hey Kevin, let’s dig into the exceptions you’re hitting with your Discord bot’s custom script parser. I’ve worked through similar regex-based parsing issues before, so here’s what’s likely going wrong and how to fix it:
Common Pitfalls & Solutions
1. Your Regex Isn’t Capturing Groups When Using match()
The critical issue here is that String.match() with the g flag returns only full matches (like "{if:3|=|0|you are|TechRax is}"), not the capture groups (the function name if and arguments 3|=|0|you are|TechRax is). When you try to process these matches, you’re probably trying to access data that doesn’t exist, throwing errors.
Fix: Use RegExp.exec() in a loop to get access to capture groups for each match:
const input = "{if:3|=|0|you are|TechRax is} {range:1|100}"; const funcRegex = /\{(.*?):(.*?)\}/g; let newString = input; let match; // Loop through each function match with capture groups while ((match = funcRegex.exec(input)) !== null) { const fullMatch = match[0]; const funcName = match[1]; const argsStr = match[2]; const args = argsStr.split('|'); // Split arguments by | let result = ''; // Handle each function type switch(funcName) { case 'if': // Validate argument count first if (args.length < 5) { console.warn(`Invalid 'if' args: ${argsStr}`); result = fullMatch; // Keep original text instead of breaking output break; } // Parse values and evaluate condition const left = Number(args[0]); const operator = args[1]; const right = Number(args[2]); let conditionMet = false; switch(operator) { case '=': conditionMet = left === right; break; case '>': conditionMet = left > right; break; case '<': conditionMet = left < right; break; // Add other operators as needed } result = conditionMet ? args[3] : args[4]; break; case 'range': // Validate numeric range args const start = Number(args[0]); const end = Number(args[1]); if (isNaN(start) || isNaN(end) || start > end) { console.warn(`Invalid 'range' args: ${argsStr}`); result = fullMatch; break; } // Generate random number in range result = Math.floor(Math.random() * (end - start + 1)) + start; break; default: // Handle unknown functions gracefully console.warn(`Unknown function: ${funcName}`); result = fullMatch; break; } // Replace only the current matched function in the string newString = newString.replace(fullMatch, result); } console.log(newString); // Example output: "TechRax is 72"
2. Unhandled Edge Cases & Invalid Input
Exceptions often pop up when users enter malformed functions (missing arguments, typos in function names, non-numeric values for math-based functions). The fix above includes:
- Argument count validation for each function
- Numeric type checks to avoid
NaNerrors - A default case for unknown functions to preserve the original text instead of crashing
3. Unexpected Behavior With Multiple Replacements
If you were using forEach on the match() result, calling replace() would replace all instances of a matching function at once. For dynamic functions like range, this means every {range:1|100} would get the same random number. The exec() loop fixes this by replacing one match at a time, ensuring each dynamic function runs independently.
Final Tips
- Add logging for invalid inputs to debug user-submitted script errors easily
- Consider adding escape characters if you need to support literal
{or}in text (e.g.,\{to represent a literal brace) - Test with edge cases like empty arguments, non-numeric values, and unknown functions to ensure your parser is robust
内容的提问来源于stack exchange,提问作者Kevin

