regex to match exact number of occurence of a sequence

Hello Experts,

I try to build a regex to match an exact number of occurence of a sequence/word :

For example "abc" and the number of occurence needed "3" and only three, no more no less

So :
abcXYZabcEFGabc match
abcXYZabcEFGabcKLMabc don't match because we find four time abc
abcXYZabcEFG don't match, only two is found
abcabcabc match

I have this : /^([^a]*a[^a]*){3}$/ but it work because I'm looking for "a" and not for a sequence "ab", "JPQ"

Thanks for your help!

Kinds Regards.
LVL 83
leakim971PluritechnicianAsked:
Who is Participating?
 
käµfm³d 👽Connect With a Mentor Commented:
Third time's a charm?

:)
^(?=(?:(?:a(?=a)|a[^b]|ab[^c]|[^a])*abc){3}(?!.*?abc)).*$

Open in new window

0
 
Patrick MatthewsConnect With a Mentor Commented:
Does it have to be RegExp?

I don't know what specific language you are using, but if you:

1) Replace "abc" with "" and

2) The resulting string is 9 characters fewer in length than the original string

then you would have a "match".
0
 
leakim971PluritechnicianAuthor Commented:
Thanks a lot for your reply.
The language is Javascript and It sound stupid but I need to use a regexp.

Something like : /^([^a]*a[^a]*){3}$/.test("abcXYZabcEFGabc") will return true or false



0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

 
Patrick MatthewsCommented:
Why must it be RegExp?
0
 
phr0zeConnect With a Mentor Commented:
Try this:

(abc[a-zA-Z]*?){3}(?!.*abc)

tested at regexpal.com
0
 
sentnerConnect With a Mentor Commented:
Can you use 2 separate regex's?  For example, this pseudocode:

if /(abc.*){3}/ then
   if /(abc.*){4}/ return false     # More than 3 matches
   else return true                      # Exactly 3 matches
else return false                        # Less than 3 matches


0
 
leakim971PluritechnicianAuthor Commented:
Why a regex ? I can use it as a parameter for example.
@phr0ze and @sentner thank you I'm going to try your propositions.
0
 
käµfm³d 👽Commented:
@phr0ze

The problem with your pattern is that the *? on the bracket expression will consume any trailing "abc" strings after the first three. Simply adding the negative lookahead does not overcome this.
0
 
käµfm³d 👽Commented:
I believe the following satisfies the requirement:
^(?=(?:(?:[^a]|a[^ab])*abc){3}(?!.*?abc)).*$

Open in new window

0
 
leakim971PluritechnicianAuthor Commented:
kaufmed this one don't match : affkaabcsjfjabckfsofabc
affk a abc sjfj abc kfsof abc

0
 
käµfm³d 👽Commented:
It seems it did not upon further testing. Revised:
^(?=(?:(?:[^a]|a[^b]|a(?=a))*abc){3}(?!.*?abc)).*$

Open in new window

0
 
käµfm³d 👽Commented:
Yeah, the double-a killed it. The modified version has this corrected.
0
 
leakim971PluritechnicianAuthor Commented:
Don't match with : abffkabcsjfjabckfsofabc

ab ffk abc sjfj abc kfsof abc
0
 
leakim971PluritechnicianAuthor Commented:
@kaufmed, yes it work this time, thanks. The "problem" with this regexp is the way we build it dynamically.
The original sequence need to have three characters for example : abc

Anyway I want to thank you a lot for your time. I'm going to use an array of regex+boolean and use the logic of @sentner

I'm going to close the question
Thank you to everyone for your suggestions, have a great weekend!
0
 
leakim971PluritechnicianAuthor Commented:
End of week, enjoy, have a nice weekend!
Thanks a lot to everyone! Have fun in your life!
0
 
käµfm³d 👽Commented:
I figured I'd throw this out there just in case, but the string shouldn't be that difficult to build dynamically; granted I don't know what your environment is like. Here is a function I created to build the pattern string:
function buildPattern(src)
{
	var basePattern = "^(?=(?:(?:@@@)*###){3}(?!.*?###)).*$";
	var temp = "";
	var t = src.charAt(0);
	
	for (i = 1; i < src.length; i++)
	{
		temp += "|" + t + "[^" + src.charAt(i) + "]";
		t += src.charAt(i);
	}

	temp = src.charAt(0) + "(?=" + src.charAt(0) + ")" + temp;
	
	return basePattern.replace(/###/g, src).replace(/@@@/, temp);
}

Open in new window

0
 
käµfm³d 👽Commented:
Of course, make sure your source strings don't contain the sequences "###" or "@@@"   :)
0
 
leakim971PluritechnicianAuthor Commented:
Thanks a lot @kaufmed!
0
 
käµfm³d 👽Commented:
Sure. Glad to help!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.