通过正则表达式拆分并在前瞻中捕获组会在结果中生成重复的片段

时间:2015-07-14 21:40:45

标签: regex

我希望有一个单行将千位分隔符插入到带有小数分隔符的数字字符串中(例如:course_title)。我的第一次尝试是将字符串拆分到剩下3位或6位数的位置,直到小数点分隔符:

78912345.12

给了我以下结果(注意原始字符串的片段是如何重复的):

console.log("5789123.45".split(/(?=([0-9]{3}\.|[0-9]{6}\.))/));

我发现“问题”(请在此处阅读问题,因为我明显的误解)来自于在先行表达式中使用组。这个简单的表达式“正确”起作用:

[ '5', '789123.', '789', '123.', '123.45' ]

执行时打印:

console.log("abcXdeYfgh".split(/(?=X|Y)/));

但是当我用括号括起[ 'abc', 'Xde', 'Yfgh' ] 时:

X|Y

结果数组如下所示:

console.log("abcXdeYfgh".split(/(?=(X|Y))/));

此外,当我将组更改为非捕获组时,一切都恢复为“正常”:

[ 'abc', 'X', 'Xde', 'Y', 'Yfgh' ]

再次产生:

console.log("abcXdeYfgh".split(/(?=(?:X|Y))/));

所以,我可以在原始表达式中做同样的技巧(改为非捕获组)(它确实有效),但我希望能解释这种我无法理解的行为。尝试在.NET中执行相同操作时,我会遇到相同的结果,因此对于正则表达式前瞻性工作方式来说,这似乎是一个基本的问题。这是我的问题:为什么捕捉群体的前瞻会产生那些“奇怪”的结果?

2 个答案:

答案 0 :(得分:1)

在正则表达式分割方法/函数内捕获正则表达式模式中的组会使捕获的文本在结果数组中显示为单独的元素(对于大多数主要语言)。

以下是C#/.NET reference

  

如果在Regex.Split表达式中使用捕获括号,则任何捕获的文本都包含在结果字符串数组中。例如,如果在捕获括号内的连字符上拆分字符串“plum-pear”,则返回的数组包含一个包含连字符的字符串元素。

以下是JavaScript reference

  

如果separator是包含捕获括号的正则表达式,则每次匹配时,捕获括号的结果(包括任何未定义的结果)都会拼接到输出数组中。但是,并非所有浏览器都支持此功能。

请注意:

会出现相同的行为
  1. PHPpreg_splitPREG_SPLIT_DELIM_CAPTURE标志):

    print_r(preg_split("/(?<=(X))/","XYZ",-1,PREG_SPLIT_DELIM_CAPTURE));
    // --> [0] => X, [1] => X, [2] => YZ

  2. Ruby(与string.split):

    "XYZ".split(/(?<=(X))/) # => X, X, YZ

  3. 但它是相反的in Java,捕获的文本不是结果数组的一部分:

    System.out.println(Arrays.toString("XYZ".split("(?<=(X))"))); // => [X, YZ]
    

    in Pythonre模块,re.split无法在零宽度断言上拆分,因此字符串根本不会被拆分

    print(re.split(r"(?<=(X))","XXYZ")) # => ['XXYZ']
    

答案 1 :(得分:1)

这是在Javascript

中执行此操作的简单方法

number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")