How do I insert a regex quantifier into a range - regex

I have this regex range
/([a-zA-Z0-9\.\-#_~!$&'()*+,;=:]+)/
for the allowable characters for a user's username. I would like to add the # char to the range but limit its quantity to 0 or 1 and have it's location be irrelevant.
I know #{0,1} is the quantifier syntax, but how do I combine it with my range to meet my specifications.
Requirements:
A - Z alphabet
0 - 9 numerals
Only 1 # allowed
Special Characters: # - _ ~ ! $ & ' ( ) * + , ; = :
Thanks

You can use a lookahead regex like this:
/^(?!(?:[^#]*#){2})[-a-zA-Z0-9.#_~!$&'()*+,;=:#]+$/
RegEx Demo
(?!(?:[^#]*#){2}) will disallow 2 # in your input thus allowing you to use 0 or 1 # in input. Also check demo.

i would like to make you Regex small by using \w in it
here is what w indicates in regex
\w : Matches any word character (alphanumeric & underscore). Only matches low-ascii characters (no accented or non-roman characters). Equivalent to [A-Za-z0-9_]
please look ahead for this,this will reduce length of your regex.
^(?!(?:[^#\n]*#){2})[\w.#_~!$&'()*+,;=:#]+$

Just copy your regex and add the # in the middle:
/^([-a-zA-Z0-9.#_~!$&'*+,;=:()]+#?[-a-zA-Z0-9.#_~!$&'*+,;=:()]+)$/
or more precisely:
/^(#|#?[-a-zA-Z0-9.#_~!$&'*+,;=:()]+|[-a-zA-Z0-9.#_~!$&'*+,;=:()]+#|[-a-zA-Z0-9.#_~!$&'*+,;=:()]+#[-a-zA-Z0-9.#_~!$&'*+,;=:()]+)$/

Related

Regex for text (string and numbers) between Pipes

I have this scenario:
Ex1:
Valid:
12345678|abcdefghij|aaaaaaaa
Invalid:
12345678|abcdefghijk|aaaaaaaaa
Which means that between pipes the maximum length is 8. How can I make in the regex?
I put this
^(?:[^|]+{0,7}(?:\|[^|]+)?$ but it´s not working
Try the following pattern:
^.{1,8}(?:\|.{1,8})*$
The basic idea is to match between one and eight characters, followed by | and another 1 to 8 characters, that term repeated zero or more times. Explore the demo with any data you want to see how it works.
Sample data:
123
12345678
abcdefghi (no match)
12345678|abcdefgh|aaaaaaaa
12345678|abcdefghijk|aaaaaaaaa (no match)
Demo here:
Regex101
When you want to match delimited data, you should refrain from using plain unrestricted .. You need to match parts between |, so you should consider [^|] negated character class construct that matches any char but |.
Since you need to limit the number of the pattern occurrences of the negated character class, restrict it with a limiting quantifier {1,8} that matches 1 to 8 consecutive occurrences of the quantified subpattern.
Use
^[^|]{1,8}(?:\|[^|]{1,8})*$
See the regex demo.
Details
^ - start of a string
[^|]{1,8} - any 1 to 8 chars other than |
(?:\|[^|]{1,8})* - 0 or more consecutive sequences of:
\| - a literal pipe symbol
[^|]{1,8} - any 1 to 8 chars other than |
$ - end of string.
Then, the [^|] can be restricted further as per requirements. If you only need to validate a string that has ASCII letters, digits, (, ), +, ,, ., /, :, ?, whitespace and -, you need to use
^[A-Za-z0-9()+,.\/:?\s-]{1,8}(?:\|[A-Za-z0-9()+,.\/:?\s-]{1,8})*$
See another regex demo.

Regex - Match unlimited no. of words of fixed length

I'm fairly new to regex. I'm looking for an expression which will return strings in which the first character is of length 1, followed by an unlimited number of words of length 3 or more.
There should be a space between each word+.
So far I have:
([A-Za-z]{1,1} [A-Za-z+]{3,100})
As it stands this only returns phrases such as:
'I will' and 'A bird'
But I would like it to return phrases like:
'I will always try' and 'A bird flew into the cage'
Any help would be appreciated. I'm using an application called 'Oracle EDQ'.
You need to apply the limiting quantifier {3,} to the [A-Za-z] group and the * (zero or more repetitions) to the outer group matching a space + the 3+-letter words:
^[A-Za-z]( [A-Za-z]{3,})*$
See regex demo. Note the use of anchors ^ and $ that is very important when you need to match characters at a specific place (here, at the start and end of a word).
Regex matches:
^ - checks the regex engine is at the beginning of a string
[A-Za-z] - Exactly 1 letter a to z and A to Z
( [A-Za-z]{3,})* - zero or more sequences of...
- a space
[A-Za-z]{3,} - 3 or more ASCII letters
$ - end of string.
You can use this regex:
^[A-Za-z](?: [A-Za-z]{3,})+$
RegEx Demo

Match this regex on perl

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])).

Match specific length x or y

I'd like a regex that is either X or Y characters long. For example, match a string that is either 8 or 11 characters long. I have currently implemented this like so: ^([0-9]{8}|[0-9]{11})$.
I could also implement it as: ^[0-9]{8}([0-9]{3})?$
My question is: Can I have this regex without duplicating the [0-9] part (which is more complex than this simple \d example)?
There is one way:
^(?=[0-9]*$)(?:.{8}|.{11})$
or alternatively, if you want to do the length check first,
^(?=(?:.{8}|.{11})$)[0-9]*$
That way, you have the complicated part only once and a generic . for the length check.
Explanation:
^ # Start of string
(?= # Assert that the following regex can be matched here:
[0-9]* # any number of digits (and nothing but digits)
$ # until end of string
) # (End of lookahead)
(?: # Match either
.{8} # 8 characters
| # or
.{11} # 11 characters
) # (End of alternation)
$ # End of string
With Perl, you could do:
my $re = qr/here_is_your_regex_part/;
my $full_regex = qr/$re{8}(?:$re{3})?$/
For those of us looking to capture different lengths of the same multiple try this.
^(?:[0-9]{32})+$
Where 32 is the multiple you want to capture all lengths for (32, 64, 96, ...).

Match letter followed by specific numeric range

I am writing a regular expression in which the string can be of 2-3 characters.
The first character has to be a Alphabet between A and H (capitals). This character has to be followed by a number between 1 and 12.
I wrote
[A-H]{1}[1-12]{1,2}
This is fine when I keyin A12 but not when I keyin A6
Please suggest.
You can't specify a range of digits like that because it is implemented as a range between characters, so [1-12] is equivalent to [12], which would only match either a 1 or a 2. Instead, try the following:
[A-H](?:1[012]|[1-9])
Here is an explanation:
[A-H] # one letter from A to H
(?: # start non-capturing group
1[012] # 1 followed by 0, 1, or 2 (10, 11, 12)
| # OR
[1-9] # one digit from 1 to 9
) # end non-capturing group
Note that the {1} after [A-H] in your original regex is unnecessary, [A-H]{1} and [A-H] are equivalent.
You may want to consider adding anchors to the regex, otherwise you would also get a partial match on a string like A20. If you are trying to match an entire string then you should use the following:
\A[A-H](?:1[012]|[1-9])\z
If it is within a larger text you could use word boundaries instead:
\b[A-H](?:1[012]|[1-9])\b
Here you go:
^[A-H]([1-9]|1[0-2])$
No need to for the {1} in your question.
The regex is anchored with ^ and $ meaning it can can be the only thing on your line.
It will not match A60 for example