Divide a credit card number into 4 pieces using a regex lookahead?

I want to write down a credit card number (in my case I always have 16 digits) in 4 pieces of 4 digits.

I managed to do this through a positive look ahead:

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

But I do not understand why the result consists of two filled empty cells:

enter image description here

I already know that I can use the "Delete empty entries" flag, but I do not after that.
However - if I change the regular expression to (?=(?:....)+$) , I get this result:

enter image description here

Question

Why does regex emit empty cells? and how can I fix my regular expression so that it produces 4 pieces in the first place (without the need to β€œtrim” these empty entries)

+5
source share
4 answers

But I don’t understand why the result consists of two filled empty cells: Let's try to break your regular expression.

Regex: (?=(?:....)*$)

Explanation: Lookahead (? =) For anything 4 times (?: ....) for zero or more. Just looking ahead and nothing will match zero width .

Since you are using a * quantifier that indicates zero or more, it matches the first zero width at the beginning or in the line, and also at the end of the line.

Visualize it from this snapshot of Regex101 Demo

[ Zero Width visualization. [2]

So, how can I select only those 3 separators in the middle?

I don't know C # very well, but this three-step method might work for you.

  • Find (\d{4}) and replace it with -\1 . The result will be -4581-4582-4583-4584 . Demo

  • Now replace first - with a search with ^- . The result will be 4581-4582-4583-4584 . Demo

  • Finally find - and separate it. Demo Used \n to replace the demo target.

Alternative Solution Inspired by Roya's answer.

Regex: (?=(?!^)(?:\d{4})+$)

Explanation:

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

Regular Expression Tracking

Since nothing is matched and only converse statements are used, it will determine the width of zero after a group of 4 digits.

Regex101 demo

+3
source

Umm, I don’t know WHY for this you need Regex. You just overload things. It’s best to just split it manually:

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

Regressive solution:

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

I think I found the answer.

Having looked at these splitters - I needed to get rid of the edges:

enter image description here

So, I thought - how can I say the regex engine is "not at the beginning of the line"?

This is exactly what (?!^) Does

So here is the new regex:

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

Result:

enter image description here

+4
source

It has already been mentioned that the quantifier * also matches at the end of the line, where there are zero group matches ahead. To avoid matching at the beginning and end, you can use \B non word boundary that matches only two word characters that do not match at the beginning and end.

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

See demo at regex101

Since lookahead does not start at the beginning or end of a line, you can even use *

+2
source

Source: https://habr.com/ru/post/1267066/


All Articles