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