为了账号安全,请及时绑定邮箱和手机立即绑定

金|Node.js - 将字符串划分为考虑引号的参数

金|Node.js - 将字符串划分为考虑引号的参数

桃花长相依 2022-09-16 21:59:52
我正在编写一个不和谐的机器人。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问题是,在英雄联盟中,允许在昵称中使用空格。同时,原因只有一个词可能不足。如果你试图这样做:机器人不会得到作为args[1],而是,将是args[1],并且将是args[2]。同时,现在将是参数[3]而不是参数[2]。!command "player one" reasonsplayer one"playerone"reasons有没有一种简单的方法来告诉javascript忽略引号内的空格,这样它就不会在那里拆分字符串?我可以使用不同的字符来拆分字符串,但是编写这样的命令感觉很奇怪,并且是补丁而不是实际的解决方案。!command-player-reasons there
查看完整描述

4 回答

?
森林海

TA贡献2011条经验 获得超2个赞

更新:

因为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 = args[1].replace(/"/g, '');`


查看完整回答
反对 回复 2022-09-16
?
守着一只汪

TA贡献1872条经验 获得超3个赞

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


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));


查看完整回答
反对 回复 2022-09-16
?
月关宝盒

TA贡献1772条经验 获得超5个赞

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


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;

}


查看完整回答
反对 回复 2022-09-16
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

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


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


如果您只支持用户名部分的引号,则更容易:


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)));


查看完整回答
反对 回复 2022-09-16
  • 4 回答
  • 0 关注
  • 159 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信