使用 Regex 前瞻将信用卡号分成 4 个块?

Split credit card number into 4 chunks using Regex lookahead?

我想将一个信用卡号(在我的例子中我总是有 16 位数字)分成 4 个 4 位数字的块。

我通过积极的展望成功地做到了:

var s="4581458245834584";
var t=Regex.Split(s,"(?=(?:....)*$)");
Console.WriteLine(t);

但我不明白为什么结果是有两个填充的空单元格:

我已经知道我可以使用 "Remove Empty Entries" 标志,但我不会在那之后。
但是 - 如果我将正则表达式更改为 (?=(?:....)+$) ,那么我会得到这个结果:

问题

为什么正则表达式会发出空单元格?以及如何修复我的正则表达式,使其首先产生 4 个块(而不必 'trim' 那些空条目)

But I don't understand why the result is with two padded empty cells: Let's try breaking down your regex.

正则表达式: (?=(?:....)*$)

解释: 前瞻 (?=) anything 4 次(?:....) 零次或多次。向前看,什么都不匹配将匹配 零宽度

由于您使用的是 * 量词 零个或多个 它匹配开头或字符串以及字符串结尾的第一个零宽度。

从这张 Regex101 Demo

的快照中将其可视化

[

So How can I select only those 3 splitters in the middle ?

我不太了解 C#,但是这 3 步方法可能适合您。

  1. 搜索 (\d{4}) 并替换为 -。结果将是 -4581-4582-4583-4584Demo

  2. 现在通过搜索 ^- 替换第一个 -。结果将是 4581-4582-4583-4584Demo

  3. 最后搜索-,然后拆分。 Demo。使用 \n 代替演示目的。

受 Royi 回答启发的替代解决方案。

正则表达式: (?=(?!^)(?:\d{4})+$)

解释:

(?=              // Look ahead for
   (?!^)         // Not the start of string
   (?:\d{4})+$   // Multiple group of 4 digits till end of string
)

由于没有任何匹配且仅使用环视断言,它将在一组 4 位数字后精确定位零宽度。

Regex101 Demo

嗯,我不知道你为什么需要正则表达式。你只是把事情复杂化了。更好的方法是手动拆分它:

var values = new List<int>();
for(int i =0;i < 4;i++)
{
    var value = int.Parse(s.Substring(i*4, 4));
    values.Add(value);
}

正则表达式解决方案:

        var s = "4581458245834584";
        var separated = Regex.Match(s, "(.{4}){4}").Groups[1].Captures.Cast<Capture>().Select(x => x.Value).ToArray();

看来我找到了答案

看看那些分离器 - 我需要去除边缘:

所以我想 - 我怎样才能告诉正则表达式引擎 "not at the start of the line "?

这正是 (?!^) 所做的

所以这是新的正则表达式:

var s="4581458245834584";
var t=Regex.Split(s,"(?!^)(?=(?:....)+$)");
Console.WriteLine(t);

结果:

已经提到 * 量词也匹配字符串的末尾,其中前面有零组匹配。为了避免在开始和结束时匹配,你可以使用 \B non word boundary 只匹配两个 word characters not giving匹配开始和结束。

\B(?=(?:.{4})+$)

See demo at regex101

因为不会在字符串的开头或结尾触发前瞻,您甚至可以 use *