使用 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 步方法可能适合您。
搜索 (\d{4})
并替换为 -
。结果将是 -4581-4582-4583-4584
。 Demo
现在通过搜索 ^-
替换第一个 -
。结果将是 4581-4582-4583-4584
。 Demo
最后搜索-
,然后拆分。 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 位数字后精确定位零宽度。
嗯,我不知道你为什么需要正则表达式。你只是把事情复杂化了。更好的方法是手动拆分它:
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})+$)
因为不会在字符串的开头或结尾触发前瞻,您甚至可以 use *
我想将一个信用卡号(在我的例子中我总是有 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 步方法可能适合您。
搜索
(\d{4})
并替换为-
。结果将是-4581-4582-4583-4584
。 Demo现在通过搜索
^-
替换第一个-
。结果将是4581-4582-4583-4584
。 Demo最后搜索
-
,然后拆分。 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 位数字后精确定位零宽度。
嗯,我不知道你为什么需要正则表达式。你只是把事情复杂化了。更好的方法是手动拆分它:
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})+$)
因为不会在字符串的开头或结尾触发前瞻,您甚至可以 use *