Regular Expression to exclude numerical emailids - regex

I have below set of sample emailids
EmailAddress
1123
123.123
123_123
123#123.123
123#123.com
123#abc.com
123mbc#abc.com
123mbc#123abc.com
123mbc#123abc.123com
123mbc123#cc123abc.c123com
Need to eliminate mailids if they contain entirely numericals before #
Expected output:
123mbc#abc.com
123mbc#123abc.com
123mbc#123abc.123com
123mbc123#cc123abc.c123com
I used below Java Rex. But its eliminating everything. I have basic knowledge in writing these expressions. Please help me in correcting below one. Thanks in advance.
[^0-9]*#.*

do you mean something like this ? (.*[a-zA-Z].*[#]\w*\.\w*)
breakdown .* = 0 or more characters [a-zA-Z] = one
letter .* = 0 or more characters #
\w*\.\w* endless times a-zA-Z0-9 with a single . in between
this way you have the emails that contains at least one letter
see the test at https://regex101.com/r/qV1bU4/3
edited as suggest by ccf with updated breakdown

The following regex only lets email adresses pass that meet your specs:
(?m)^.*[^0-9#\r\n].*#
Observe that you have to specify multi-line matching ( m flag. See the live demo. The solution employs the embedded flag syntax m flag. You can also call Pattern.compile with the Pattern.MULTILINE argument. ).
Live demo at regex101.
Explanation
Strategy: Define a basically sound email address as a single-line string containing a #, exclude strictly numerical prefixes.
^: start-of-line anchor
#: a basically sound email address must match the at-sign
[^...]: before the at sign, one character must neither be a digit nor a CR/LF. # is also included, the non-digit character tested for must not be the first at-sign !
.*: before and after the non-digit tested for, arbitrary strings are permitted ( well, actually they aren't, but true syntactic validation of the email address should probably not happen here and should definitely not be regex based for reasons of reliability and code maintainability ). The strings need to be represented in the pattern, because the pattern is anchored.

Try this one:
[^\d\s].*#.+
it will match emails that have at least one letter or symbol before the # sign.

Related

How do I match a colon with no values after it?

I'm new to the website and to Regular Expression as well.
So I want to bookmark a list of Emails that have no value after the colons ":" as highlighted in the picture below.
Here is an example:
abcdef#gmail.com:123456
abcdEF452#gmail.com:test123##NEW
abcdef#gmail.com:
abcdef#gmail.com:
I only want to bookmark the last two ones so it would be like this:
abcdef#gmail.com:
abcdef#gmail.com:
The following regex will match the "pre-colon" pattern if and only if it is followed by nothing but whitespace until the end of the line:
\w+#\w+\.\w+:\s*$
View on regex101
Note that matching email addresses with 100% correctness is more complicated than this, but this will likely do for your use case.
If you only want to find strings that end with a colon, then all you need is :$.
I find this request a bit odd, perhaps if you could elaborate a bit more on your use case I may be able to provide a better approach or solution.
Now, I think that this expression should work the way you expect:
[\w\.]+#[a-z0-9][a-z0-9-]*[a-z0-9]?
Add the colon sign at the end if you need to match for the colon sign as well.
I noticed that the other proposed expressions don't account for email addresses with a dot in the username part or with dashed in the domain part. You may use a combination of all the solutions if you are more familiar with RegEx. I highly recommend you test the expression before moving it to production, you can do further tests easily on this page https://regexr.com/.
[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
Will be a more adequate RegEx since the Internet Engineering Task Force established limits on how an email address can be formatted and this accounts for those additional characters. More details on this page https://www.mailboxvalidator.com/resources/articles/acceptable-email-address-syntax-rfc/.
As a friendly reminder, Stack Overflow can be best used when you have already invested some effort in fixing some problem, rather than having a community member provide you with a straight answer. This and other suggestions are listed on this other page https://stackoverflow.com/tour.
Try this:
[a-zA-Z]+#[a-zA-Z]+: # Only a-zA-Z, numbers are not accepted
Note: the last character is a space " "
[\w+]+#[\w+]+: # \w+ = Matches one or more [A-Za-z0-9_]
Without a space it will matches only these with no character after the colon.
[\w+]+#[\w+]+.*:$ # Matches only when there is also .XXX. For example: .com or .de
Given this:
abcdEF452#gmail.com:test123##NEW
There are three parts to this:
Before the #.
Between the # and the :
After the :
If we assume (1) has to be there and not empty.
If we assume (2) has to be there and not empty.
If we assume (3) the ':' is required by the trailing part can be empty.
I don't want to make assumptions about other requirements.
Then I would use:
[^#]+#[^:]+:.*$
Meaning:
[^#] => Anything apart from the '#' character.
[^#]+ => The above 1 or more times.
[^#]+# => The above followed by '#' character.
[^:] => Anything apart from the ':' character.
[^:]+ => The above 1 or more times.
[^:]+: => The above followed by ':' character.
.* => Any character 0 or more times.
$ end of line.
So if we want to mkae sure we only find things that don't have anything after the ':' we can simplify a bit.
[^#]+#[^:]+:$
Make sure we have the '#' and ':' parts and they are none empty. But the colon is followed by the end of line.
If you don't care about part (1) or (2) we can simplify even more.
[^:]+:$
Line must contain a : don't care what is in front as long as there is a least one character before the ':' and zero after.
Final simplification.
:$
If you don't care about anything except that the colon is not followed by anything.

Interesting easy looking Regex

I am re-phrasing my question to clear confusions!
I want to match if a string has certain letters for this I use the character class:
[ACD]
and it works perfectly!
but I want to match if the string has those letter(s) 2 or more times either repeated or 2 separate letters
For example:
[AKL] should match:
ABCVL
AAGHF
KKUI
AKL
But the above should not match the following:
ABCD
KHID
LOVE
because those are there but only once!
that's why I was trying to use:
[ACD]{2,}
But it's not working, probably it's not the right Regex.. can somebody a Regex guru can help me solve this puzzle?
Thanks
PS: I will use it on MYSQL - a differnt approach can also welcome! but I like to use regex for smarter and shorter query!
To ensure that a string contains at least two occurencies in a set of letters (lets say A K L as in your example), you can write something like this:
[AKL].*[AKL]
Since the MySQL regex engine is a DFA, there is no need to use a negated character class like [^AKL] in place of the dot to avoid backtracking, or a lazy quantifier that is not supported at all.
example:
SELECT 'KKUI' REGEXP '[AKL].*[AKL]';
will return 1
You can follow this link that speaks on the particular subject of the LIKE and the REGEXP features in MySQL.
If I understood you correctly, this is quite simple:
[A-Z].*?[A-Z]
This looks for your something in your set, [A-Z], and then lazily matches characters until it (potentially) comes across the set, [A-Z], again.
As #Enigmadan pointed out, a lazy match is not necessary here: [A-Z].*[A-Z]
The expression you are using searches for characters between 2 and unlimited times with these characters ACDFGHIJKMNOPQRSTUVWXZ.
However, your RegEx expression is excluding Y (UVWXZ])) therefore Z cannot be found since it is not surrounded by another character in your expression and the same principle applies to B ([ACD) also excluded in you RegEx expression. For example Z and A would match in an expression like ZABCDEFGHIJKLMNOPQRSTUVWXYZA
If those were not excluded on purpose probably better can be to use ranges like [A-Z]
If you want 2 or more of a match on [AKL], then you may use just [AKL] and may have match >= 2.
I am not good at SQL regex, but may be something like this?
check (dbo.RegexMatch( ['ABCVL'], '[AKL]' ) >= 2)
To put it in simple English, use [AKL] as your regex, and check the match on the string to be greater than 2. Here's how I would do in Java:
private boolean search2orMore(String string) {
Matcher matcher = Pattern.compile("[ACD]").matcher(string);
int counter = 0;
while (matcher.find())
{
counter++;
}
return (counter >= 2);
}
You can't use [ACD]{2,} because it always wants to match 2 or more of each characters and will fail if you have 2 or more matching single characters.
your question is not very clear, but here is my trial pattern
\b(\S*[AKL]\S*[AKL]\S*)\b
Demo
pretty sure this should work in any case
(?<l>[^AKL\n]*[AKL]+[^AKL\n]*[AKL]+[^AKL\n]*)[\n\r]
replace AKL for letters you need can be done very easily dynamicly tell me if you need it
Is this what you are looking for?
".*(.*[AKL].*){2,}.*" (without quotes)
It matches if there are at least two occurences of your charactes sorrounded by anything.
It is .NET regex, but should be same for anything else
Edit
Overall, MySQL regular expression support is pretty weak.
If you only need to match your capture group a minimum of two times, then you can simply use:
select * from ... where ... regexp('([ACD].*){2,}') #could be `2,` or just `2`
If you need to match your capture group more than two times, then just change the number:
select * from ... where ... regexp('([ACD].*){3}')
#This number should match the number of matches you need
If you needed a minimum of 7 matches and you were using your previous capture group [ACDF-KM-XZ]
e.g.
select * from ... where ... regexp('([ACDF-KM-XZ].*){7,}')
Response before edit:
Your regex is trying to find at least two characters from the set[ACDFGHIJKMNOPQRSTUVWXZ].
([ACDFGHIJKMNOPQRSTUVWXZ]){2,}
The reason A and Z are not being matched in your example string (ABCDEFGHIJKLMNOPQRSTUVWXYZ) is because you are looking for two or more characters that are together that match your set. A is a single character followed by a character that does not match your set. Thus, A is not matched.
Similarly, Z is a single character preceded by a character that does not match your set. Thus, Z is not matched.
The bolded characters below do not match your set
ABCDEFGHIJKLMNOPQRSTUVWXYZ
If you were to do a global search in the string, only the italicized characters would be matched:
ABCDEFGHIJKLMNOPQRSTUVWXYZ

Regular expression for validating complicated username

So, the conditions are:
At least 1 character, max 20 characters
Starts with [a-zA-Z]
Contains [a-zA-Z0-9.-]
Ends with [a-zA-Z0-9]
My expression is:
^(?=[a-zA-Z])+[a-zA-Z0-9.-]*[a-zA-Z0-9]{1,20}$
It works nicely. However, it doesn't work properly with a username's length. I can enter a thirty-character username and still find a match. What's wrong with it?
I tend to find complicated regexps a poor choice when wanting to validate a string against multiple rules. They cause unreadable code that's difficult to maintain.
How about (in pseudocode)
.length >= 1 && .length <= 20
&& /^[a-z0-9.-]+$/i
&& /^[a-z]/i
&& /[a-z0-9]$/i
i.e. check the length, then check the legal character validity, then check the opening and closing characters, exactly as described in your question text.
You could also combine the first two lines so that you're only using regexps:
/^[a-z0-9.-]{1,20}$/i
&& /^[a-z]/i
&& /[a-z0-9]$/i
I'd be surprised if this was slower than a one-liner regexp, but it's certainly more readable.
If it contains only [a-zA-Z0-9.-], starts with [a-zA-Z] and ends with [a-zA-Z0-9], it doesn't start with [-0-9.] and doesn't end with [.-]
^(?![-0-9.])[a-zA-Z0-9.-]{1,20}(?<![.-])$
Note: Works only in regex flavors, that support negative lookbehind.
Test at regex101
Try this:
^[a-zA-Z]$|^(?=.{2,20}$)[a-zA-Z][a-zA-Z0-9.-]*[a-zA-Z0-9]$
You could use the below regex,
^(?=.{1,20}$)[a-zA-Z][a-zA-Z0-9.-]*[a-zA-Z0-9]$
DEMO
If the string does not start with [a-zA-Z] the regex will fail. The rest is easier to understand.
^(?=[a-zA-Z])[a-zA-Z0-9.-]{0,19}[a-zA-Z0-9]$
DEMO
The following is a fairly simple solution:
^[a-zA-Z]$|^[a-zA-Z]{1}[a-zA-Z0-9.-]{0,18}[a-zA-Z0-9]{1}$
Broken down:
Either: a single character in the group [a-zA-Z]
Or: Exactly one character in group [a-zA-Z], up to 18 characters in the group [a-zA-Z0-9.-] and finally 1 character from the group [a-zA-Z0-9].
Matches correctly against the following:
Valid
Valid.UserName
Valid1-1UserName
0-Invalid
Invalid.
Invalid-ThisIsTooLong
V

Lookaround assertions in Perl

im confused what is the use of these lookaround assertions in perl?
example this one:
(?=pattern)
or the positive lookahead. So here's my questions:
How are these useful? what sort of instances they are used?
And related to question 1, why would i want to look ahead of the regex pattern? isnt it more work? looking ahead and then executing the pattern matching again.
I need a very clear example if possible. Thanks
To uppercase what's in between commas, you could use:
(my $x = 'a,b,c,d,e') =~ s/(?<=,)([^,]*)(?=,)/ uc($1) /eg; # a,B,C,D,e
a,b,c,d,e
Pass 1 matches -
Pass 2 matches -
Pass 3 matches -
If you didn't use lookarounds, this is what you'd get,
(my $x = 'a,b,c,d,e') =~ s/,([^,]*),/ ','.uc($1).',' /eg; # a,B,c,D,e
a,b,c,d,e
Pass 1 matches ---
Pass 2 matches ---
Not only does the lookahead avoid repetition, it doesn't work without it!
Another somewhat common use is as part of a string equivalent to [^CHAR].
foo(?:(?!foo|bar).)*bar # foo..bar, with no nested foo or bar
You can use it to narrow down character classes.
\w(?<!\d) # A word char that's not a digit.
Although this can now be done using (?[ ... ]).
It's also useful in more esoteric patterns.
/a/ && /b/ && /c/
can be written as
/^(?=.*?a)(?=.*?b).*?c/s
lookahead lets you check for a pattern without actually matching it.
When you do a(?=b) ,you would match a if its followed by b. Note:it doesn't match b.
So,
1>You can extract hello(without #) from #hello# using
(?<=#)hello(?=#)
2>You can validate passwords with requirements such as a password must have 2 digits,2 letters or more with any other character
^(?=(.*\d){2})(?=(.*[a-z]){2}).*$
Try doing above without lookahead ,you would realize it's importance
I have found lookaheads especially useful for checking multiple conditions. For example, consider a regex that checks that a password has at least one lowercase, one uppercase, one numeric, and one symbol character, and is at least 8 characters in length:
^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9]).{8,}$
Try to devise a regex to do the same thing without lookahead assertions! It's possible, but it's extremely cumbersome.
Meanwhile, I've found lookbehinds especially useful for checking boundary conditions—that is, for example, matching a string of 0's, unless it's preceded by another number, like 1000067.
These are my experiences but certainly there are many more practical uses and the way everyone uses a tool can vary from person to person.
There are many reasons to use lookarounds, e.g.
limiting the substring that is considered to be matched: s/(?<=[0-9])+(?=[0-9])/-/ instead of s/([0-9])+([0-9])/$1-$2/.
and-ing various conditions together: /(?=\p{Uppercase}\p{Lowercase})\p{InBasicLatin}{2,}/.
Lookaround assertions is useful when you need a pattern to help locate the match but you don't want the pattern to be part of what is captured.
Here's a simple scenario with lookahead assertion:
Let's say I have
my $text = '98 degrees, 99 Red Balloons, 101 Dalmatians'
and I want to change the number of red balloons from its previous value to 9001, so I use
$text =~ s/\d+(?=Red Balloons)/9001/;

Simple regex - finding words including numbers but only on occasion

I'm really bad at regex, I have:
/(#[A-Za-z-]+)/
which finds words after the # symbol in a textbox, however I need it to ignore email addresses, like:
foo#things.com
however it finds #things
I also need it to include numbers, like:
#He2foo
however it only finds the #He part.
Help is appreciated, and if you feel like explaining regex in simple terms, that'd be great :D
/(?:^|(?<=\s))#([A-Za-z0-9]+)(?=[.?]?\s)/
#This (matched) regex ignores#this but matches on #separate tokens as well as tokens at the end of a sentence like #this. or #this? (without picking the . or the ?) And yes email#addresses.com are ignored too.
The regex while matching on # also lets you quickly access what's after it (like userid in #userid) by picking up the regex group(1). Check PHP documentation on how to work with regex groups.
You can just add 0-9 to your regex, like so:
/(#[A-Za-z0-9-]+)/
Don't think any more explanation is needed since you've been able to come this far by yourself. 0-9 is just like a-z (though numeric ofcourse).
In order to ignore emailaddresses you will need to provide more specific requirements. You could try preceding # with (^| ) which basically states that your value MUST be preceeded by either the start of the string (so nothing really, though at the start) or a space.
Extending this you can also use ($| ) on the end to require the value to be followed by the end of the string or a space (which means there's no period allowed, which is requirement for a valid emailaddress).
Update
$subject = "#a #b a#b a# #b";
preg_match_all("/(^| )#[A-Za-z0-9-]+/", $subject, $matches);
print_r($matches[0]);