将字符串拆分为数组而不删除分隔符?

Posted

技术标签:

【中文标题】将字符串拆分为数组而不删除分隔符?【英文标题】:Split string into array without deleting delimiter? 【发布时间】:2014-07-01 06:36:11 【问题描述】:

我有一个类似的字符串

 "asdf a  b c2 "

我想把它拆分成这样的数组:

["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]

使用string.split(" ") 删除空格,结果如下:

["asdf", "a", "", "b", "c2"]

我想过插入额外的分隔符,例如

string.replace(/ /g, "| |").replace(/||/g, "|").split("|");

但这会产生意想不到的结果。

【问题讨论】:

【参考方案1】:

与其拆分,不如将其视为提取包含分隔符或 不是 分隔符的连续字符的字符串:

'asdf a  b c2 '.match(/\S+|\s/g)
// result: ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]
'asdf a  b. . c2% * '.match(/\S+|\s/g)
// result: ["asdf", " ", "a", " ", " ", "b.", " ", ".", " ", "c2%", " ", "*", " "]

对比赛的更莎士比亚式的定义是:

'asdf a  b c2 '.match(/ |[^ ]+/g)

或(不致)+。

【讨论】:

@Jack 我没有,但这似乎有效!显然,我需要学习正则表达式.. \S+ 是什么意思? @gandalf3 \S\s 的反义词。也可以写成[^\s] +1 但请注意:不需要将其包装在非捕获组 ((?: )) 中。 'asdf a b c2 '.match(/\S+|\s/g) 是一样的【参考方案2】:

使用积极的前瞻:

"asdf a  b c2 ".split(/(?= )/)
// => ["asdf", " a", " ", " b", " c2", " "]

后期编辑编辑: 正如我在 cmets 中所说,缺乏后视功能使这有点棘手。如果所有单词仅由字母组成,您可以使用\b 单词边界匹配器来假装lookbehind:

"asdf a  b c2 ".split(/(?= )|\b/)
// => ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]

但是一旦你输入一些标点符号,它就会崩溃,因为它不仅会在空格上中断:

"asdf-eif.b".split(/(?= )|\b/)
// => ["asdf", "-", "eif", ".", "b"]

如果您确实有不想中断的非字母,那么我也会建议一种后处理方法。

Post-think EDIT:这是基于 JamesA 的原始想法,但改进为不使用 jQuery,并正确拆分:

function chop(str) 
  var result = [];
  var pastFirst = false;
  str.split(' ').forEach(function(x) 
    if (pastFirst) result.push(' ');
    if (x.length) result.push(x);
    pastFirst = true;
  );
  return result;

chop("asdf a  b c2 ")
// => ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]

【讨论】:

这非常适合我在问题中写的内容,但我刚刚意识到我在示例中犯了一个错误。请参阅我编辑的问题。 @gandalf3 你不希望它们作为字符串? @limelights 我希望每个空间都在一个元素中。一个元素中不应该有空格 + 其他任何东西。 @limelights:原来分割是在每个空格之前;现在是每个空格之前和之后。不幸的是,javascript 没有lookbehind,所以这有点困难...... 谢谢!这很好用,但接受了杰克的回答,因为它更短(尽管该解决方案确实会拆分任何空白字符,而不仅仅是空格。但这对我来说很好)。如果可以的话,我会接受这两者.. (+1 btw)【参考方案3】:

我很惊讶还没有人提到这一点,但为了完整起见,我会在这里发布。如果您的表达式中有捕获组,则.split 会将捕获的子字符串作为单独的条目包含在结果数组中:

"asdf a  b c2 ".split(/( )/)  // or /(\s)/
// ["asdf", " ", "a", " ", "", " ", "b", " ", "c2", " ", ""]

注意,这与您指定的所需输出完全不同,因为它在两个连续空格之间和最后一个空格之后包含一个空字符串。

如有必要,您可以像这样从结果数组中过滤掉所有空字符串:

"asdf a  b c2 ".split(/( )/).filter(String)
// ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]

但是,如果这是您正在寻找的内容,我可能会建议您使用 @Jack's solution。

【讨论】:

哎呀,对不起.. 最后的空字符串是错字。我已经编辑了我的问题。 @gandalf3 好的,我已经提供了一个替代解决方案,可以在这种情况下为您提供所需的结果。【参考方案4】:

试试clean-split:

const cleanSplit = require("clean-split");

cleanSplit("a-b-c", "-");
//=> ["a", "-", "b", "-", "c"]

cleanSplit("a-b-c", "-",  anchor: "before" );
//=> ["a-", "b-", "c"]

cleanSplit("a-b-c", "-",  anchor: "after" );
//=> ["a", "-b", "-c"]

在底层,它使用的逻辑改编自:

Kai's non-anchored splitting regex Amadan's positive lookahead regex added in ES2018 的正则表达式正则表达式 escape-string-regexp 解决问题。

在你的情况下,你可以这样做:

const cleanSplit = require("clean-split");

cleanSplit("asdf a  b c2 ", " ");
//=> ["asdf", " ", "a", " ", " ", "b", " ", "c2", " "]

【讨论】:

【参考方案5】:

你可以使用一点 jQuery

var toSplit = "asdf a  b c2 ".split(" ");
$.each(toSplit, 
    function(index, value)  
        if (toSplit[index] == '')  toSplit[index] = ' ' 
    
);

这将创建您正在寻找的输出,而其他元素上没有前导空格。

【讨论】:

在较新的环境中不需要 jQuery - jQuery.each 是一个穷人的 [].foreach

以上是关于将字符串拆分为数组而不删除分隔符?的主要内容,如果未能解决你的问题,请参考以下文章

Java:使用正则表达式拆分字符串而不删除分隔符[重复]

拆分逗号分隔的字符串,同时删除空格和空条目

将逗号分隔的字符串拆分为数组?

如何通过分隔符将字符串拆分为数组?

如何将字符串拆分为分隔符也是标记的数组? [复制]

PHP:将字符串拆分为数组,例如没有分隔符的爆炸