6

用一个例子可以更好地解释这一点。我想实现这样的拆分:

two-separate-tokens-this--is--just--one--token-another

->

["two", "separate", "tokens", "this--is--just--one--token", "another"]

我天真地尝试过str.split(/-(?!-)/),它不会匹配第一次出现的双定界符,但它会匹配第二次(因为它后面没有定界符):

["two", "separate", "tokens", "this-", "is-", "just-", "one-", "token", "another"]

我有比遍历字符串更好的选择吗?

顺便说一句,下一步应该将两个连续的分隔符替换为一个,所以它通过重复来逃避分隔符......所以最终结果将是这样的:

["two", "separate", "tokens", "this-is-just-one-token", "another"]

如果这一步可以实现,那应该是非常棒的!

4

6 回答 6

8

str.match(/(?!-)(.*?[^\-])(?=(?:-(?!-)|$))/g);

检查这个小提琴。


解释:

非贪婪模式(?!-)(.*?[^\-])匹配不以破折号字符开头和结尾的字符串,并且模式(?=(?:-(?!-)|$))要求此类匹配后跟单个破折号字符或行尾。修饰符/g强制函数match查找所有事件,而不仅仅是单个(第一个)事件。


编辑 (基于OP的评论):

str.match(/(?:[^\-]|--)+/g);

检查这个小提琴。

解释:

模式(?:[^\-]|--)将匹配非破折号字符或双破折号字符串。Sign+表示,与先前模式的这种匹配应该尽可能多地相乘。修饰符/g强制函数match查找所有事件,而不仅仅是单个(第一个)事件。

笔记:

Pattern /(?:[^-]|--)+/g 也适用于 Javascript,但 JSLint 需要-在方括号内转义,否则会出现错误。

于 2012-08-13T18:13:36.567 回答
2

你需要一个否定的lookbehind断言以及你的否定lookahead:

(?<!-)-(?!-)

http://regexr.com?31qrn

不幸的是,javascript 正则表达式解析器不支持否定的lookbehinds,我相信唯一的解决方法是事后检查您的结果并删除任何可能导致lookbehind 断言失败的匹配项(或者在这种情况下,将它们组合回一个匹配项)。

于 2012-08-13T18:08:14.847 回答
2

@Ωmega 在使用matchinstead of方面有正确的想法split,但他的正则表达式比它需要的更复杂。试试这个:

s.match(/[^-]+(?:--[^-]+)*/g);

它的读取方式完全符合您的预期:使用一个或多个非连字符,如果遇到双连字符,请使用它并继续使用非连字符。根据需要重复。


编辑:显然源字符串可能包含两个或多个连续连字符的运行,不应将其视为分隔符。这可以通过将 a 添加+到第二个连字符来处理:

s.match(/[^-]+(?:--+[^-]+)*/g);

您还可以使用{min,max}量词:

s.match(/[^-]+(?:-{2,}[^-]+)*/g);
于 2012-08-13T19:05:16.510 回答
0

我不知道如何纯粹使用 JS 中的正则表达式引擎来做到这一点。你可以这样做,比手动解析少一点涉及:

var str = "two-separate-tokens-this--is--just--one--token-another";
str = str.replace(/--/g, "#!!#");
var split = str.split(/-/);
for (var i = 0; i < split.length; i++) {
    split[i] = split[i].replace(/#!!#/g, "--");
}

工作演示:http: //jsfiddle.net/jfriend00/hAhAB/

于 2012-08-13T18:12:06.563 回答
0

您可以像这样(受本文启发)这样(受本文启发),在没有负面后视的情况下实现这一点(正如@jbabey 提到的,这些在 JS 中不受支持):

\b-\b
于 2012-08-13T18:16:58.817 回答
0

鉴于正则表达式在边缘情况下不是很好(比如 5 个连续的定界符),我不得不处理用单个定界符替换双定界符(然后它会变得很棘手,因为'----'.replace('--', '-')'---'而不是'--')我写了一个函数循环遍历字符并一次性完成所有操作(尽管我担心使用字符串累加器可能会很慢:-s)

f = function(id, delim) {
    var result = [];
    var acc = '';
    var i = 0;
    while(i < id.length) {
        if (id[i] == delim) {
            if (id[i+1] == delim) {
                acc += delim;
                i++;
            } else {
                result.push(acc);
                acc = '';
            }
        } else {
            acc += id[i];
        }
        i++;
    }

    if (acc != '') {
        result.push(acc);
    }

    return result;
    }

和一些测试:

> f('a-b--', '-')
["a", "b-"]
> f('a-b---', '-')
["a", "b-"]
> f('a-b---c', '-')
["a", "b-", "c"]
> f('a-b----c', '-')
["a", "b--c"]
> f('a-b----c-', '-')
["a", "b--c"]
> f('a-b----c-d', '-')
["a", "b--c", "d"]
> f('a-b-----c-d', '-')
["a", "b--", "c", "d"]

(如果最后一个标记为空,则意味着跳过)

于 2012-08-14T08:57:58.723 回答