【问题标题】:JS | Node.js - Divide a string into arguments considering quotation marksJS | Node.js - 考虑引号将字符串划分为参数
【发布时间】:2020-09-22 22:50:12
【问题描述】:

我正在编写一个不和谐的机器人。 Discord 是一个带有聊天功能的社交平台,您可以在那里编写机器人代码。

为了触发机器人命令,机器人会读取发送到聊天室的每条消息。它以字符串的形式发送给他。

通过使用这个:var args = msg.content.split(' ');,机器人将每个单词分成一个数组。现在,我可以这样做了:if (args[0] === '!command') { //code }

我的机器人会跟踪英雄联盟的玩家。我希望能够输入名称并添加跟踪原因。所有这些都将进入数据库。乍一看似乎很简单,我可以这样做:

if (args[0] === '!command') {
  var player = args[1];
  var reason = args[2];
}

现在,如果我发送 !command player1 reasons,机器人就会正确处理。

问题是,在英雄联盟中,您的昵称中有空格是允许的。同时,原因可能只有一个词。如果您尝试这样做:!command "player one" reasons 机器人不会将 player one 作为 args[1],相反,"player 将是 args[1],one" 将是 args[2]。同时,reasons 现在将是 args[3] 而不是 args[2]。

有没有一种简单的方法来告诉 javascript 忽略引号内的空格,这样它就不会在那里拆分字符串?

我可以使用不同的字符来拆分字符串,但是编写像!command-player-reasons there 这样的命令感觉很奇怪,而且是一个补丁而不是实际的解决方案。

【问题讨论】:

标签: javascript node.js discord discord.js


【解决方案1】:

更新:

因为 OP 似乎对语言不太熟悉,所以我选择提供一个易于阅读的答案。 正确的方法是使用正则表达式捕获组:https://stackoverflow.com/a/18647776/16805283


这将检查 `message.content` 中是否有引号,并更改获取 args 数组的方式。如果没有找到引号,它会退回到您自己的代码来生成 args 数组。请记住,这仅适用于 ** 在 `message.content` 中正好有 2 个 ** 引号,因此不应使用引号
// Fake message object as an example
const message = {
  content: '!command "Player name with a lot of spaces" reason1 reason2 reason3'
};

const { content } = message; 
let args = [];
if (content.indexOf('"') >= 0) {
  // Command
  args.push(content.slice(0, content.indexOf(' ')));
  // Playername
  args.push(content.slice(content.indexOf('"'), content.lastIndexOf('"') + 1));
  // Reasons
  args.push(content.slice(content.lastIndexOf('"') + 2, content.length));
} else {
  args = content.split(' ');
}
// More code using args

如果你想要不带引号的 playerName:

playerName = args[1].replace(/"/g, '');`

【讨论】:

    【解决方案2】:

    你可以在这里使用正则表达式:

    const s = `!command "player one" some reason`;
    
    function getArgsFromMsg1(s) {
      const args = []
      if ((/^!command/).test(s)) {
        args.push(s.match(/"(.*)"/g)[0].replace(/\"/g, ''))
        args.push(s.split(`" `).pop())
        return args
      } else {
        return 'not a command'
      }
    
    }
    
    // more elegant, but may not work
    function getArgsFromMsg2(s) {
      const args = []
      if ((/^!command/).test(s)) {
        args.push(...s.match(/(?<=")(.*)(?=")/g))
        args.push(s.split(`" `).pop())
        return args
      } else {
        return 'not a command'
      }
    }
    
    console.log(getArgsFromMsg1(s));
    console.log(getArgsFromMsg2(s));

    【讨论】:

      【解决方案3】:

      对于机器人用户来说,使用不同的字符来分割两个参数是可能的,但可能不太复杂。

      例如!command player one, reasons 如果您知道 ,(或 |=&gt; 等)不是有效用户名的一部分。

      如果你只支持用户名部分的引号,那就更简单了:

      const command = `!command`;
      const msg1 = {content: `${command} "player one" reasons ggg`};
      const msg2 = {content: `${command} player reasons asdf asdf`};
      
      function parse({content}) {
        if (!content.startsWith(command)) {
          return; // Something else
        }
        content = content.replace(command, '').trim();
        const quotedStuff = content.match(/"(.*?)"/);
        if (quotedStuff) {
          return {player: quotedStuff[1], reason: content.split(`"`).reverse()[0].trim()};
        } else {
          const parts = content.split(' ');
          return {player: parts[0], reason: parts.slice(1).join(' ')};
        }
        console.log(args);
      }
      
      [msg1, msg2].forEach(m => console.log(parse(m)));

      【讨论】:

        【解决方案4】:

        我建议你分别解析命令和它的参数。它将承认编写更灵活的命令。例如:

        var command = msg.content.substring(0, msg.content.indexOf(' '));
        var command_args_str = msg.content.substring(msg.content.indexOf(' ') + 1);
        switch(command) {
            case '!command':
                var player = command_args_str.substring(0, command_args_str.lastIndexOf(' '));
                var reason = command_args_str.substring(command_args_str.lastIndexOf(' ') + 1);
                break;
        }
        

        【讨论】:

          猜你喜欢
          • 2013-02-17
          • 1970-01-01
          • 2021-01-19
          • 1970-01-01
          • 1970-01-01
          • 2016-04-12
          • 2019-06-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多