I am fairly new with Perl, and even more so with regex.
Have been trying to match the following, but without success:
First, 3 to 4 letters (ideally case insensitive)
Optionally a space (but not mandatory)
Then, also optionally a known big-case letter (M) and a number out of 1,2,3
An example of a valid string would be abc, but also DEFG M2. Invalid would be mem M, for example
What I have so far is:
$myExpr ~= m/^[a-z,A-z]{3,4}M[1,2,3]$/i
Not sure how to make the M and numbers optional
Why don't you try the following regular expression for it:
$myExpr =~ m/^([a-zA-Z]{3,4})(\s|)(M|)([1-3]|)$/;
([a-zA-Z]{3,4}) - Group of any character in this class: [a-zA-Z] with 3 to 4 repetition.
(\s|) - Either there will be a white-space(space) or not.
(M|) - Either there will be a Uppercase M or not.
([1-3]|) - Either there will any charter this class: [1-3] or not.
(OR) Try the following
I personally recommend this
$myExpr =~ m/^([a-zA-Z]{3,4})(\s{0,1})(M{0,1})([1-3]{0,1})$/;
([a-zA-Z]{3,4}) - Group of any character in this class: [a-zA-Z] with 3 to 4 repetition i.e., it should contain minimum of 3 characters and maximum of 4.
(\s{0,1}) - Group of \s with 0 to 1 repetition i.e., it's optional.
(M{0,1}) - Group of character M with 0 to 1 repetition i.e., it's optional.
([1-3]{0,1}) - Group of any digit from 1 to 3 with 0 to 1 repetition i.e., it's optional.
Group your optional symbols with (?:) and use "zero or one" quantifier ?.
$myExpr =~ m/^[a-zA-Z]{3,4}(?: M[123])?$/
I've also fixed errors in your regexp: you don't use , in character classes - that'd literraly mean "match ,", fixed A-Z range and removed /i modifier, since you didn't say if you need lower case M and first range already covers both small and big letters.
You can use the following regex. You don't need to use comma inside character class []. And also remove i as you need to match with M.
$myExpr ~= m/^[a-zA-z]{3,4}(?: M[123])?$/
If you think your space is optional, then again add a ? after that space too (i.e. (?: ?M[123])).
Related
I'm trying to search through a file for a set of parentheses with eight characters inside them, all 1s or 0s, with at least one 1.
I currently am using the regex below, enumerating all possible such parentheses sets, i.e. brute forcing it.
Is there a better way to do this?
My regex:
(11111110)|(11111101)|(11111100)|(11111011)|(11111010)|(11111001)|(11111000)|...|(11111111) etc.
Use
grep -oP '\((?=[01]{8}\))0*1[10]*\)' file
See the regex demo.
Details
-o - outputs matches rather than matching lines
P - enables PCRE regex engine
Pattern
\( - a ( char
(?=[01]{8}\)) - a positive lookahead that requires eight 0 or 1 chars up to to a )
0* - 0+ zeros
1 - a 1 char
[10]* - 0 or more zeros or ones
\) - a ).
You may use this regex,
\((?=[10]{8})(?=.*1.*).{8}\)
Explanation:
\( --> Matches a literal ( (starting brace)
(?=[10]{8}) --> Look ahead ensuring next eight characters are composed of zero and one only
(?=.*1.*) --> Look ahead ensuring the presence of at least one '1' character
.{8} --> matches exactly eight characters
\) --> Matches a literal ) (closing brace)
Demo
This regex could also work:
(?!\(00000000\))\(\d{8}\)
I am trying to make a regex that is used in an exception.
Therefore it must return false for these sentences (the leading digits are included in the strings):
3.{17} this is italics and should break.{18}
4. this is another sentence and should break.
5. This is another sentence and should break.
And it must return true for these:
There are 2 reasons for this 1. you are here and 2. you are communicating.
Is it 2? they wanted to know.
1 digit at the beginning but with 1. with a period should return true.
In other words, if the beginning of the string is a number followed by a period, it should return false (even if "\{\d+\}" follows it optionally) and the character following the space does not matter. And it must return true if the number and period (or ! or ?) is embedded in the sentence followed by a lower case character, in other cases it must be false.
As a further note: this goes into a java properties file, and the value is then passed to a perl5 regex engine to return broken text.
I try to express it in one expression, but somehow I cannot get it right.
This is what have come up with until now:
^([^0-9\.]+[\.]|
[^\.!\?]*[\?!]+[\?!\.]+|
[0-9]+[^\?!\.]+[\?!\.]+|
[^0-9]*[0-9]+[^\?!\.]+[\?!\.]+)
(\{\d+\}[\u0020\u00A0]|
[\u0020\u00A0]*)[a-z]
I seem to arrived at an impasse and can't see what is I have wrong.
Thanks for any advice.
Update:
A simpler format with look-ahead: ^(?!\d+\.)[^.!?]*[.!?]+(\{\d+\}\s|\s*)\p{Ll} based on the comments.
You may use
^(?!\d+\.)[^.!?]*[.!?]+(\{\d+\}\s|\s*)\p{Ll}
See the regex demo.
The pattern matches:
^ - start of string anchor
(?!\d+\.) - a negative lookahead that will fail the match if its pattern is matched at the start of the string: 1+ digits followed with a dot
[^.!?]* - 0+ chars other than ., ! and ?
[.!?]+ - 1 or more ., ! or ? symbols
(\{\d+\}\s|\s*) - either a { + 1 or more digits + } or 0+ whitespaces (if you are not interested in the value captured with this capturing group, you may turn it into a non-capturing one by adding ?: after the first ().
\p{Ll} - a lowercase letter (if a u modifier is used, it will also match all Unicode lowercase letters).
The regular expression in question is
(\d{3,4}[.-]?)+
sample text
707-7019-789
My progress so far
( )+ a capturing group, capturing one or more
\d{3,4} digit, in quantities 3 or 4
[.-]? dot (or something) or hyphen, in quantities zero or one <-- this is the part I'm interested in
From my understanding this should match 3 or 4 digit number, followed by a dot (or anything, since dot matches anything) or a hyphen, bundled in a group, one or more times. Why doesn't this matches a
707+123-4567
then?
. in a character group [] is just a literal ., it does not have the special meaning "anything". [.-]? means "a dot or a hyphen or nothing", because the entire group is made optional with the ?.
[.-]?
What this means literally:
character class [.-]
Match only one out of the following characters: . and - literally.
lazy quantifier ?
Repeat the last token between 0 and 1 times, as few times as possible.
The brackets remove the functionality of the dot.
Brackets mean "Range"/"Character class".
Thus you are saying Choose from the list/range/character class .-
You aren't saying choose from the list "anything"- (anything is the regular meaning of .)
as I go through the regex101 quiz/lessons, I am supposed to match an IP address (without leading zeros).
Now the following
^[^0]+[0-9]+\\.[^0]+[0-9]+\\.[^0]+[0-9]+\\.[^0]+[0-9]+$
matches 23.34.7433.33
but fails to match single digit numbers like 1.2.3.4
Why is this so, when my + is supposed to match "1 to infinite" times...?
You are in fact matching more than 2 digits for each number in the IP address because you have:
[^0]+[0-9]+
[^0]+ matches at least one character, and [0-9]+ matches at least 1 character. Both will match 'at least 2 characters' (characters being in scope of the character classes).
Also 23.34.7433.3 doesn't match your regex for the reason I stated above.
And you might try this regex for the purpose you stated:
^(?:[1-9][0-9]{0,2}\.){3}[1-9][0-9]{0,2}$
[1-9][0-9]{0,2} will match up to 3 digits, with a non leading 0.
EDIT: You mentioned in a comment that 0.0.0.0 (single digit zeroes) are to be accepted as well. The modified regex from above would be:
^(?:(?:[1-9][0-9]{0,2}|0)\.){3}(?:[1-9][0-9]{0,2}|0)$
Assuming you want to check an IPv4, I suggest you this pattern:
^(?<nb>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])(?>\.\g<nb>){3}$
I have defined a named subpattern nb to make the pattern shorter, but if you prefer, you can rewrite all and replace \g<nb>:
^(?>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9])){3}$
Numbers greater than 255 are not allowed.
pattern details:
The goal is to describe what is allowed:
numbers with 3 digits that begins with "2" can be followed by a digit in [0-4] and a digit in [0-9] OR by 5 and a digit in [0-5] because it can exceed 255.
numbers with 3 digits that begins with "1" can be followed by any two digits.
any number with 2 digits that doesn't begin with "0"
any number with 1 digit (zero included)
If I add one by one these rules, I obtain
2(?>[0-4][0-9]|5[0-5])
2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2}
2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2} | [1-9][0-9]
2(?>[0-4][0-9]|5[0-5]) | 1[0-9]{2} | [1-9][0-9] | [0-9]
Now I have a definition for allowed numbers. I can reduce a little the size of the pattern replacing [1-9][0-9] | [0-9] by [1-9]?[0-9]
Then you only have to add the dot repeat the subpattern four times: x.x.x.x
But since there is only three dots, I write the first number and I repeat 3 times a group that contains a dot and a number:
2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9] # the first number
(?>\.2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9]){3} # the group repeated 3 times
To be sure that the string doesn't contain anything else that the IP I described, I add anchors for the start of string ^ and for the end of string $, then the string begins and ends with the IP.
To reduce the size of a pattern you can define a named group which allows to reuse the subpattern it contains,
Then you can rewrite the pattern like this:
^
(?<nb> 2(?>[0-4][0-9]|5[0-5])|1[0-9]{2}|[1-9]?[0-9] ) # named group definition
(?> \. \g<nb> ){3} # \g<nb> is the reference to the subpattern named nb
$
[0-9]+ should be [0-9]*
* matches 0 or more.
+ matches 1 or more.
You already have the case [^0] <--- this actually wrong because it will match letters also.
besides that it will match the first character that's NOT zero then at least one number after that.
It should be written as
[1-9][0-9]*
This essentially checks the first letter and sees if its a number that's between 1-9 then the next numbers(0 nums to infinite nums) after that is a number 0-9.
Then this will come out to.
^[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*$
Edit live on Debuggex
cleaning it up.
^(?:[1-9][0-9]*\.){3}[1-9][0-9]*$
this should work...
^(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*\.|[0-9])(?:[1-9][0-9]*|[0-9])$
cleaned up.
^(?:(?:[1-9][0-9]*|0)\.){3}(?:[1-9][0-9]*|0)$
Your regex would match ABCDEFG999.FOOBSR888 etc, because [^0] is any character other than a zero, and bith character classes are required by the +.
I think you want this:
^[1-9]\d*(\\.[1-9]\d*){3}$
having replaced various verbose expressions with their equivalent, this is 4 groups of digits each starting with a non-zero.
Actually the problem is far more complicated, because your approach (once corrected) allows 999.999.999.999, which is not a valid IP.
It might be because you need at least two digits between two dots '.'
try using this pattern: ^[^0]+[0-9]*\.[^0]+[0-9]*\.[^0]+[0-9]*\.[^0]+[0-9]*$
to match ip address you should use this pattern:
\b(?:\d{1,3}.){3}\d{1,3}\b
taken from here:
http://www.regular-expressions.info/examples.html
I am looking for some help on creating a regular expression that would work with a unique input in our system. We already have some logic in our keypress event that will only allow digits, and will allow the letter A and the letter M. Now I need to come up with a RegEx that can match the input during the onblur event to ensure the format is correct.
I have some examples below of what would be valid. The letter A represents an age, so it is always followed by up to 3 digits. The letter M can only occur at the end of the string.
Valid Input
1-M
10-M
100-M
5-7
5-20
5-100
10-20
10-100
A5-7
A10-7
A100-7
A10-20
A5-A7
A10-A20
A10-A100
A100-A102
Invalid Input
a-a
a45
4
This matches all of the samples.
/A?\d{1,3}-A?\d{0,3}M?/
Not sure if 10-A10M should or shouldn't be legal or even if M can appear with numbers. If it M is only there without numbers:
/A?\d{1,3}-(A?\d{1,3}|M)/
Use the brute force method if you have a small amount of well defined patterns so you don't get bad corner-case matches:
^(\d+-M|\d+-\d+|A\d+-\d+|A\d+-A\d+)$
Here are the individual regexes broken out:
\d+-M <- matches anything like '1-M'
\d+-\d+ <- 5-7
A\d+-\d+ <- A5-7
A\d+-A\d+ <- A10-A20
/^[A]?[0-9]{1,3}-[A]?[0-9]{1,3}[M]?$/
Matches anything of the form:
A(optional)[1-3 numbers]-A(optional)[1-3 numbers]M(optional)
^A?\d+-(?:A?\d+|M)$
An optional A followed by one or more digits, a dash, and either another optional A and some digits or an M. The '(?: ... )' notation is a Perl 'non-capturing' set of parentheses around the alternatives; it means there will be no '$1' after the regex matches. Clearly, if you wanted to capture the various bits and pieces, you could - and would - do so, and the non-capturing clause might not be relevant any more.
(You could replace the '+' with '{1,3}' as JasonV did to limit the numbers to 3 digits.)
^A?\d{1,3}-(M|A?\d{1,3})$
^ -- the match must be done from the beginning
A? -- "A" is optional
\d{1,3} -- between one and 3 digits; [0-9]{1,3} also work
- -- A "-" character
(...|...) -- Either one of the two expressions
(M|...) -- Either "M" or...
(...|A?\d{1,3}) -- "A" followed by at least one and at most three digits
$ -- the match should be done to the end
Some consequences of changing the format. If you do not put "^" at the beginning, the match may ignore an invalid beginning. For example, "MAAMA0-M" would be matched at "A0-M".
If, likewise, you leave $ out, the match may ignore an invalid trail. For example, "A0-MMMMAAMAM" would match "A0-M".
Using \d is usually preferred, as is \w for alphanumerics, \s for spaces, \D for non-digit, \W for non-alphanumeric or \S for non-space. But you must be careful that \d is not being treated as an escape sequence. You might need to write it \\d instead.
{x,y} means the last match must occur between x and y times.
? means the last match must occur once or not at all.
When using (), it is treated as one match. (ABC)? will match ABC or nothing at all.
I’d use this regular expression:
^(?:[1-9]\d{0,2}-(?:M|[1-9]\d{0,2})|A[1-9]\d{0,2}-A?[1-9]\d{0,2})$
This matches either:
<number>-M or <number>-<number>
A<number>-<number> or A<number>-A<number>
Additionally <number> must not begin with a 0.