1

I'm trying to create a command parser for a Discord bot for when it receives a message, but I am having issues with dealing with nested quotes. I have made it so that it can parse a string with double quotes and flags, but it does not handle nested quotes.

Here are my requirements:

  • Handle double quotes.
  • Handle nested double quotes.
  • Handle flags (can be anywhere after !command).
    • A flag without a specified value defaults to a value of true/1.

For example, the following string:

!command that --can "handle double" quotes "and \"nested double\" quotes" --as --well=as --flags="with values"

...should result in the following arguments: command, that, handle double, quotes, and "nested double" quotes and the following flags: "can": true, "as": true, "well": "as", "flags": "with values".

Here is what I have so far:

// splits up the string into separate arguments and flags
const parts = content.slice(1).trim().match(/(--\w+=)?"[^"]*"|[^ "]+/g)
  .map(arg => arg.replace(/^"(.*)"$/, '$1'));

// separates the arguments and flags
const [ args, flags ] = parts.reduce((parts, part) => {
  // check if flag or argument
  if (part.startsWith('--')) {
    // check if has a specified value or not
    if (part.includes('=')) {
      // parses the specified value
      part = part.split('=');
      const value = part.slice(1)[0];

      parts[1][part[0].slice(2)] = value.replace(/^"(.*)"$/, '$1');
    } else {
      parts[1][part.slice(2)] = true;
    }
  } else {
    parts[0].push(part);
  }

  return parts;
}, [[], {}]);

This currently parses into the following arguments: command, that, handle double, quotes, and \, nested, double\, quotes and the following flags: "can": true, "as": true, "well": "as", "flags": "with values".

1 Answer 1

1

I modified the first RegEx to allow \" in the middle of quoted values. The following line:

const parts = content.slice(1).trim().match(/(--\w+=)?"[^"]*"|[^ "]+/g)

...changed to:

const parts = content.slice(1).trim().match(/(--\S+=)?"(\\"|[^"])*"|[^ "]+/g)

Modifications

  • The "[^"]*" section was changed to "(\\"|[^"])*" to allow \" to validate, preventing the quoted value from being terminated by quotes with backslashes before them.
  • I changed the \w in (--\w+=)? to a \S resulting in (--\S+=)? to allow more letters to validate.
Sign up to request clarification or add additional context in comments.

2 Comments

This doesn't work generally. With the test input cc -E -Dquote='"\""' -c test.c, the third matched group should be -Dquote='"\""', but it is not. See regex101.com/r/mtDDNU/1 - I don't know how to fix your regex, or if it's fixable; just wanted to point out in case someone else considers this wrong answer as a solution
BTW, my counter example defines a preprocessor macro named quote which is a quoted string containing one character: the double quote (")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.