Regex Exactly N or M Times

Regex exactly n OR m times

There is no single quantifier that means "exactly m or n times". The way you are doing it is fine.

An alternative is:

X{m}(X{k})?

where m < n and k is the value of n-m.

Regex group match exactly n times

Your first regex is incorrect because it asserts that id is present after the first three items.

Your second regex matches the string incorrectly because .* matches hyphens as well.

You should use this regex:

/^(?:[^-]+-){2}id/

Here is a regex demo!

And if you feel a need to anchor a regex to the end, use /^(?:[^-]*-){2}id.*$/!


As mentioned by Tim Pietzcker, consider asserting id at the end of the item:

/^(?:[^-]+-){2}id(?![^-])/

Here is an UPDATED regex demo!

RegExp Quantifier to Match Pattern Exactly n or m Times Instead of n to m Times

You can use negative lookbehind/lookahead to accomplish this:

Here's one possible way to accomplish what you're trying to do.

/(?<!\d)(\d{2}|\d{4})(?!\d)/

This says - find a 2 or 4 digit number that is not preceded or followed by another number. This differs from the answer above in that it will match ALL 2 and 4 digit numbers including those that are not surrounded by spaces such as the "12" in the string "abc12def".

Which way you choose will depend on what in particular you are looking for.

Regex to match at least n times but not more than m times

Although it's often written as {min,max} in tutorials and references, the enumerated quantifier does not mean not more than max. If it sees three hyphens, -{1,3} will consume all three, but it doesn't care what the next character is (if there is one). It's just like all other quantifiers in this regard: it consumes as much as it can, then it hands control to the next part of the regex.

That's why the other responders suggested using an end anchor ($). If you can't use an anchor, or don't want to, you can use a negative lookahead instead:

/^%\*-{1,3}(?!-)/

How does {m}{n} (exactly n times twice) work?

When I input your regex in RegexBuddy using the Java regex syntax, it displays following message

Quantifiers must be preceded by a token that can be repeated «{2}»

Changing the regex to explicitly use a grouping ^(\d{1}){2} solves that error and works as you expect.


I assume that the java regex engine simply neglects the error/expression and works with what has been compiled so far.

Edit

The reference to the IEEE-Standard in @piet.t's answer seems to support that assumption.

Edit 2 (kudos to @fncomp)

For completeness, one would typically use (?:)to avoid capturing the group. The complete regex then becomes ^(?:\d{1}){2}

Regex to match exactly n occurrences of letters and m occurrences of digits

You can use

^(?=[^A-Z]*[A-Z][^A-Z]*$)(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$

See the regex demo (a bit modified due to the multiline input). In Java, do not forget to use double backslashes (e.g. \\d to match a digit).

Here is a breakdown:

  • ^ - start of string (assuming no multiline flag is to be used)
  • (?=[^A-Z]*[A-Z][^A-Z]*$) - check if there is only 1 uppercase letter (use \p{Lu} to match any Unicode uppercase letter and \P{Lu} to match any character other than that)
  • (?=[^a-z]*[a-z][^a-z]*$) - similar check if there is only 1 lowercase letter (alternatively, use \p{Ll} and \P{Ll} to match Unicode letters)
  • (?=(?:\D*\d){6}\D*$) - check if there are six digits in a string (=from the beginning of the string, there can be 0 or more non-digit symbols (\D matches any character but a digit, you may also replace it with [^0-9]), then followed by a digit (\d) and then followed by 0 or more non-digit characters (\D*) up to the end of string ($)) and then
  • [a-zA-Z0-9]{8} - match exactly 8 alphanumeric characters.
  • $ - end of string.

Following the logic, we can even reduce this to just

^(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$

One condition can be removed as we only allow lower- and uppercase letters and digits with [a-zA-Z0-9], and when we apply 2 conditions the 3rd one is automatically performed when matching the string (one character must be an uppercase in this case).

When using it with Java matches() method, there is no need to use ^ and $ anchors at the start and end of the pattern, but you still need it in the lookaheads:

String s = "K82v6686";
String rx = "(?=[^a-z]*[a-z][^a-z]*$)" + // 1 lowercase letter check
"(?=(?:\\D*\\d){6}\\D*$)" + // 6 digits check
"[a-zA-Z0-9]{8}"; // matching 8 alphanum chars exactly
if (s.matches(rx)) {
System.out.println("Valid");
}

Regex, That Matches No more Than n Occurrences

You can specify a character, or you can generalize it to all characters.

Also, not sure if you're trying to test or match the whole string, but assume

it's the whole string.

Generalized

^(?:(\w)(?!\1{2})|\W)+$

Explained

 ^                       # Beginning of string
(?: # Cluster
( \w ) # (1), a word character
(?! \1{2} ) # Not 2 more of same in a sequence
| # or,
\W # Not a word character
)+ # End Cluster, 1 to many times
$ # End of string

You could substitute specific characters instead of \w and \W

by replacing what you want.

Example for character a it would be a and [^a].

^(?:(a)(?!\1{2})|[^a])+$

or more than one like [abc] and [^abc]

^(?:([abc])(?!\1{2})|[^abc])+$

Regex matching exactly 3 or exactly 7 characters

To match either 3 or 7 characters, you could first match 3 characters and optionally 4 more;

^[^*]{3}(?:[^*]{4})?\*(.*)

[^*]{3} matches 3 characters that aren't an asterisk

(?:[^*]{4})? optionally matches 4 characters that are not an asterisk. ?: makes it a non capturing group since you're not interested in the content.

Regex101 to test with.



Related Topics



Leave a reply



Submit