For Java:
Quantifiers documentation
X, exactly n times: X{n}
X, at least n times: X{n,}
X, at least n but not more than m times: X{n,m}
For Java:
Quantifiers documentation
X, exactly n times: X{n}
X, at least n times: X{n,}
X, at least n but not more than m times: X{n,m}
The finite repetition syntax uses {m,n} in place of star/plus/question mark.
From java.util.regex.Pattern:
X{n} X, exactly n times
X{n,} X, at least n times
X{n,m} X, at least n but not more than m times
All repetition metacharacter have the same precedence, so just like you may need grouping for *, +, and ?, you may also for {n,m}.
ha*matches e.g."haaaaaaaa"ha{3}matches only"haaa"(ha)*matches e.g."hahahahaha"(ha){3}matches only"hahaha"
Also, just like *, +, and ?, you can add the ? and + reluctant and possessive repetition modifiers respectively.
System.out.println(
"xxxxx".replaceAll("x{2,3}", "[x]")
); "[x][x]"
System.out.println(
"xxxxx".replaceAll("x{2,3}?", "[x]")
); "[x][x]x"
Essentially anywhere a * is a repetition metacharacter for "zero-or-more", you can use {...} repetition construct. Note that it's not true the other way around: you can use finite repetition in a lookbehind, but you can't use * because Java doesn't officially support infinite-length lookbehind.
References
- regular-expressions.info/Repetition
Related questions
- Difference between
.*and.*?for regex regex{n,}?==regex{n}?- Using explicitly numbered repetition instead of question mark, star and plus
- Addresses the habit of some people of writing
a{1}b{0,1}instead ofab?
- Addresses the habit of some people of writing
regular expression - How to search for any repeating character, X number of times - Vi and Vim Stack Exchange
How to find a pattern that repeats up to N times (but not more than N times)?
Regex to find a pattern repeating at least n times - Stack Overflow
Regex: Repeat pattern n times, with variation on final repetition
I am using the Python re library.
I know if I want to just match a pattern that occurs an indefinite number of times I can just use (pattern)+, but what if I want to match a pattern that occurs up to N times, but no more?
I believe I've improved on your pattern slightly:
/(\/\w{30,})(?:.+?\1){3,}?/s
Demo link: https://regex101.com/r/aNdURv/1
Key changes:
1. Why stop at 50 characters? Shouldn't matter how long the word is as long as it is at least 30. So I removed "50" from the first group.
2. You don't need to capture each repeat, just to count it towards the total you are aiming for (3 or more), so I added "?:" to the second group.
3. You don't need it to find all matching repeats, meaning it can be lazy and stop as long as it finds at least 3. So I added "?" to the end.
You can try this (slight modification of your regex)-
(\/\w{30,50})(.*?\1){3,}
Demo here
(\s+(\w*\.*\w*);){12}
The {n} is a "repeat n times"
if you want "12 - 13" times,
(\s+(\w*\.*\w*);){12,13}
if you want "12+" times,
(\s+(\w*\.*\w*);){12,}
How about using:
[x.group() for x in re.finditer(r'(\s+(\w*\.*\w*);)*', text)]
Did you find the findall method yet? Or consider splitting at ;?
map(lambda x: x.strip(), s.split(";"))
is probably what you really want.
You need to use a back-reference to your capture group. Here is an example regex:
(.)\1{2}
Regex explained:
(.)is a capture group that captures literally anything a single time\1is a back-reference to the group you just captured (that single character){2}is a quantifier, which matches the previous token (the\1) exactly twice.
Note that, to capture a single character n times, you have to specify {n - 1} as the quantifier because the first match was already captured by (.).
I believe the following should do what you'r after:
^(?!([psr]*?([psr])\2{4})\2)(?1)(?2)*$
See an online demo
^- Start-line anchor;(?!- Open a negative lookahead;([psr]*?([psr])\2{4})\2)- A nested 1st capture group to match 0+ (Lazy) characters of[psr]upto another nested 2nd capture group of any of those characters. Right after is a backreference to the 2nd capture group which we match 4 times. After that we match the content of the 2nd capture group once more to avoid it occur 6+ times before we close the negative lookahead;
(?1)- Match the same subpattern as the 1st group;(?2)*- Match the same subpattern as the 2nd group 0+ (Greedy) times upto;$- End-line anchor.
I suppose this would be short for something like:
^(?![psr]*?([psr])\1{5})[psr]*?([psr])\2{4}[psr]*$
The full pcre that will match the strings you listed (and those that start with a ,) might be:
grep -P '^([0-9]+(-[0-9]+)?(,|$))+$'
How have we got there?
The most basic element to match is a digit, lets assume that [0-9], or the simpler \d in PCRE, is a correct regex for a English (ASCII) digit. Which might as well not be. It could match Devanagari numerals, for example. Then you would need to write: [0123456789] to be precise.
Then, a run of digits would be matched by [0-9]+.
After a number (1 or 3 or 26) ther could be a dash '-' followed by one or several digits ( a number again ):
[0-9]+(-[0-9]+)?
Where the ? makes the dash-number sequence optional.
Then, each of those numbers: 3 (or number ranges: 4-9) should be followed by a comma , (several times):
([0-9]+(-[0-9]+)?,)+
Except that the last comma might be missing:
([0-9]+(-[0-9]+)?(,|$))+
And, if required, a leading comma might be present:
(^|,)([0-9]+(-[0-9]+)?(,|$))+
It is a very good idea to anchor the regex to the beginning and end of the text tested:
^((^|,)([0-9]+(-[0-9]+)?(,|$))+)$
You may test and edit the PCRE regex in this site
If the leading comma should be rejected, use:
^(([0-9]+(-[0-9]+)?(,|$))+)$
That leaves no optional interpretations to the regex machine. All must be matched, and anything that is not matched gets rejected.
It may be written as an (GNU) extended regex:
grep -E '^(([0-9]+(-[0-9]+)?(,|$))+)$'
As a Basic Regular Expression (BRE):
grep '^\(\([0-9]\{1,\}\(-[0-9]\{1,\}\)\{0,1\},\{0,1\}\)\{1,\}\)$'
Where the comma , is optional {0,1}, the regex engine might take some decisions about what to match.
Descriptive Regex?
A more descriptive regex, with spaces and comments might be had by starting it with (?x) in pcregrep
pcregrep '(?x) # tell the regex engine to allow
# white space and comments.
(?(DEFINE) # subroutines that will be used.
(?<nrun> [0-9]+) # run of digits (n-run).
# define a range pair. A number run followed by
# an optional ( dash and another number run )
(?<range> (?&nrun) (-(?&nrun))? ) # range pair.
(?<sep> ,) # separator used.
) # end of definitions.
# Actual regex to use:
# (range) that ends in a (sep)
# or is at the end of the line,
# several times (+).
^( (?&range) ((?&sep)|$) )+$
' file
This regex (once compiled) is exactly equivalent to the original one and will run equally fast. Of course, there is an (negligible) additional time used to compile the regex.
Test example is here
Using awk to break down each line into comma-delimited fields, and then splitting those fields on dashes into sub-fields, while discarding lines that contains unwanted fields or sub-fields:
BEGIN { FS = "," }
{
for (i = 1; i <= NF; ++i) {
# Only the 1st field is allowed to be
# empty, but only if there are further
# fields (avoids empty lines).
if ($i == "" && (i != 1 || NF == 1)) next
# If the field is split on dashes, it
# should split into no more than two
# elements.
if ((n = split($i, a, "-")) > 2) next
# Each split-up element needs to be made
# up of decimal digits only.
for (j = 1; j <= n; ++j)
if (a[j] !~ "^[[:digit:]]+$") next
}
# The current line is ok to print.
print
}
This would be used like
awk -f script file
where script holds the awk program.
Or, as "once-liner":
awk -F, '{for(i=1;i<=NF;++i){if(($i==""&&(i!=1||NF==1))||((n=split($i,a,"-"))>2))next;for(j=1;j<=n;++j)if(a[j]!~"^[[:digit:]]+$")next}};1' file
You could easily add a check for "backward ranges" (e.g. 5-2) after the j loop:
if (n == 2 && a[1] > a[2]) next
Try following regex:
^[abc]{3}(,[abc]{3})*$
^...$ from the start till the end of the string
[...] one of the given character
...{3} three time of the phrase before
(...)* 0 till n times of the characters in the brackets
What you're asking it to find with your regex is "at least one triple of letters a, b, c" - that's what "+" gives you. Whatever follows after that doesn't really matter to the regex. You might want to include "$", which means "end of the line", to be sure that the line must all consist of allowed triples. However in the current form your regex would also demand that the last triple ends in a comma, so you should explicitly code that it's not so. Try this:
re.match('([abc][abc][abc],)*([abc][abc][abc])$'
This finds any number of allowed triples followed by a comma (maybe zero), then a triple without a comma, then the end of the line.
Edit: including the "^" (start of string) symbol is not necessary, because the match method already checks for a match only at the beginning of the string.