【问题标题】:Javascript split by spaces but not those in quotesJavascript由空格分隔,但不是引号
【发布时间】:2014-09-04 10:55:26
【问题描述】:

目标是在空格处拆分字符串,但不拆分引号中的文本数据或将其与相邻文本分开。

输入实际上是一个包含值对列表的字符串。如果值值包含空格,则用引号括起来。我需要一个返回值对元素数组的函数,如下例所示:

示例输入:

'a:0 b:1 moo:"foo bar" c:2'

预期结果:

a:0,b:1,moo:foo bar,c:2(长度为 4 的数组)

我检查了许多其他问题,但没有一个(我发现)似乎能解决我的问题。大多数似乎在引号内的空格处拆分,或者将“moo:”和“foo bar”拆分为单独的部分。

任何帮助将不胜感激, 克雷格

【问题讨论】:

标签: javascript regex string split


【解决方案1】:

您可以使用此正则表达式进行拆分:

var s = 'a:0 b:1 moo:"foo bar" c:2';

var m = s.split(/ +(?=(?:(?:[^"]*"){2})*[^"]*$)/g);
//=> [a:0, b:1, moo:"foo bar", c:2]

RegEx Demo

仅当它在引号之外时才在空格上拆分,方法是使用正向前瞻确保空格后有偶数个引号。

【讨论】:

  • +1,这太棒了,不过我真的想要一个更彻底的解释:)
  • 感谢@epoch:这是在引号是平衡且未转义的假设下工作的。如果空格在引号之外,则空格后面总是会有 0 个或偶数个引号,直到行尾。这正是这个前瞻(?=(?:(?:[^"]*"){2})*[^"]*$) 正在做的事情。
  • 哇,太棒了。我发现的其他正则表达式都没有你的答案 anubhava 有效。希望我们能更多地了解它是如何工作的。也可以按照示例删除引号吗?不过这没什么大不了的。
  • 但是您仍然选择接受另一个答案,该答案与您在问题中提出的要求不完全一致,并且在最终结果中也返回 moo:"foo bar"。
  • 警告,/ +(?=(?:(?:[^"]*"){2})*[^"]*$)/ 是一个非常慢的模式,如果你有很长的字符串,如果你不想遇到减速,考虑使用不同的表达式(例如described here)。
【解决方案2】:

您可以稍微不同地处理它并使用Regular Expression 来分割空格后跟单词字符和冒号(而不是不在引号部分中的空格):

var str = 'a:0 b:1 moo:"foo bar" c:2',
    arr = str.split(/ +(?=[\w]+\:)/g);
/* [a:0, b:1, moo:"foo bar", c:2] */

Demo jsFiddle

这个正则表达式是做什么的?
它在空格字符上查找文字匹配,然后使用Positive Lookahead 断言可以匹配下一部分:
[\w]+ = 匹配介于 1 和 1 之间的任何单词字符 [a-zA-Z0-9_]无限次。
\: = 匹配一次: 字符(反斜杠转义)。
g = 全局修饰符 - 第一次匹配时不返回。

Demo Regex101 (with explanation)

【讨论】:

  • 这比 anubhavas 正则表达式要短得多。我对他们了解得不够多,但似乎在做同样的工作,其他人支持另一种解决方案,但现在都没有省略结果中的引号,但这没什么大不了的。
  • 再次阅读,我看到了您的解决方案的优雅。这完全符合问题描述。它实际上使值文本中的引号的使用过时了。
  • 我已经完成了这个,我可以在代码中以某种方式将空格和 ' ' & ':' 作为变量,我不知道如何将它添加到这种正则表达式中。
【解决方案3】:

它必须是一个正则表达式有什么特殊原因吗?

var str = 'a:0 b:1 moo:"foo bar" c:2';

var parts = [];
var currentPart = "";
var isInQuotes= false;

for (var i = 0; i < str.length, i++) {
  var char = str.charAt(i);
  if (char === " " && !isInQuotes) {
    parts.push(currentPart);
    currentPart = "";
  } else {
    currentPart += char;
  }
  if (char === '"') {
    isInQuotes = !isInQuotes;
  }
}

if (currentPart) parts.push(currentPart);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 2023-04-05
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    相关资源
    最近更新 更多