I'm trying to validate usernames when using a tag function against these criteria:
Only contains alphanumeric characters, underscore and dot.
Dot can't be at the end or start of a username (e.g .username / username.).
Dot and underscore can't be next to each other (e.g user_.name).
Dot can't be used multiple times in a row (e.g. user..name).
The username ends when there is a character other than the allowed characters (e.g. #user#next or #user/nnnn would only validate user as a valid username)
Another username can only be written after a space. (e.g. #user #next would validate two usernames while #user#next would only validate user)
I have tried this so far:
^(?=.{8,20}$)(?![.])(?!.*[.]{2})[a-zA-Z0-9.]+(?<![.])$ and have dealt the multiple usernames problem with for loops.
I was wondering what would be the best way to implement something like this (e.g. regex, for loops, combination). I tried using regex but realised it is very specific and can get complicated.
Use the following regex:
(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]
(?!\.): Negative lookahead assertion to ensure the name cannot begin with a '.'
(?![a-zA-Z._]*(?:\._|_\.|\.\.)): Negative lookahead assertion that the name does not contain ._ nor _. nor .. in succession.
[a-zA-Z._]*[a-zA-Z_]: Ensures the name is at least one-character long and does not end with ..
See Regex Demo
However, the results are not necessarily what you might expect since you want to stop scanning a name when you come to the first character that is not part of a valid name but you continue scanning looking for more valid names. So when the input is, for example, .user, you stop scanning when you see the . because you know that a name cannot begin with .. But you then resume scanning and still end up scanning user as a valid name.
let text = 'user user_xyx_abc user__def user_.abc user._abc user..abc user_abc. .user';
let regexp = /(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]/g;
let matches = text.matchAll(regexp);
for (let match of matches) {
console.log(match);
}
Ideally, your input would contain only a single user name that you are validating and the entire input should match your regex. Then, you would use anchors in your regex:
^(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]$
See Regex Demo
But given your current circumstances, you might consider splitting your input on whitespace, trimming extra whitespace from the beginning and end of the strings, and then use the above regex on each individual user name:
let text = 'user user_xyx_abc user__def user_.abc user._abc user..abc user_abc. .user ';
let names = text.split(/\s+/);
let regexp = /^(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]$/;
for (name of names) {
if (regexp.test(name))
console.log(name);
}
Related
I'm trying to create a regex search in Datatables which matches a user who belongs to all selected groups.
Example:
User A belongs to Users, Other, Other Users
User B belongs to Users, Other
If Users and Other Users are selected as filters, only user A should show in the table. The problem I'm having is that both users are showing when these filters are selected. I don't think the regex is matching exact strings and, after looking through multiple other answers, I don't seem to be able to get it to do so.
My solution:
if (!this.items.length) {
table.column(i).search('');
} else {
let regex = '^';
this.items.forEach(v => regex += `(?=.*\\b${v}\\b)`);
regex += '.*$'
table.column(i).search(regex, true, false, true)
}
Which results in: ^(?=.*\bUsers\b)(?=.*\bOther Users\b).*$
However, the user belonging to Users,Other is still being returned.
You can enforce a comma or start/end of string check before and after each of your search term:
this.items.forEach(v => regex += "(?=.*(?:[^,]|^)${v}(?![^,]))");
Or, if the JavaScript environment supports lookbehinds:
this.items.forEach(v => regex += "(?=.*(?<![^,])${v}(?![^,]))");
The (?:[^,]|^) / (?<![^,]) (equal to (?<=,|^)) part requires start of string position or a comma right before your search term and the (?![^,]) negative lookahead requires a comma or end of string immediately to the right of the current position ((?![^,]) is equal to (?=,|$) positive lookahead).
I have a sentence where I need to extract the last oocurance of the matching string
https://regex101.com/r/CRR5zi/2
That is in the above example the expression only needs to select the last occurance and not the first one "Universal Serial Bus"
U.* S.* B.*
used to enable all types of communication services on the Universal Serial Bus is an example here
I have tried with
You are selecting any character that follows U, S or B.
Change your regex to less greedy (and possible remove /i flag to select only upper-case letters)
(U\w+ S\w+ B\w+)
Example
Just match them all (globally) and take the last match from the result.
const your_regex_pattern = /U.*?S.*?B.*?(?=\s|$)/g;
Is that what you need? (Note the case insensitivity has been removed, otherwise you have to avoid matching "anything" with ".", instead only match non-whitespaces) like:
const your_insensitive_regex_pattern = /U[\S]*?\s*S[\S]*?\s*B[\S]*?(?=\s|$)/gmi;
I want to write a regular expression, in JavaScript, for finding the string starting and ending with :.
For example "hello :smile: :sleeping:" from this string I need to find the strings which are starting and ending with the : characters. I tried the expression below, but it didn't work:
^:.*\:$
My guess is that you not only want to find the string, but also replace it. For that you should look at using a capture in the regexp combined with a replacement function.
const emojiPattern = /:(\w+):/g
function replaceEmojiTags(text) {
return text.replace(emojiPattern, function (tag, emotion) {
// The emotion will be the captured word between your tags,
// so either "sleep" or "sleeping" in your example
//
// In this function you would take that emotion and return
// whatever you want based on the input parameter and the
// whole tag would be replaced
//
// As an example, let's say you had a bunch of GIF images
// for the different emotions:
return '<img src="/img/emoji/' + emotion + '.gif" />';
});
}
With that code you could then run your function on any input string and replace the tags to get the HTML for the actual images in them. As in your example:
replaceEmojiTags('hello :smile: :sleeping:')
// 'hello <img src="/img/emoji/smile.gif" /> <img src="/img/emoji/sleeping.gif" />'
EDIT: To support hyphens within the emotion, as in "big-smile", the pattern needs to be changed since it is only looking for word characters. For this there is probably also a restriction such that the hyphen must join two words so that it shouldn't accept "-big-smile" or "big-smile-". For that you need to change the pattern to:
const emojiPattern = /:(\w+(-\w+)*):/g
That pattern is looking for any word that is then followed by zero or more instances of a hyphen followed by a word. It would match any of the following: "smile", "big-smile", "big-smile-bigger".
The ^ and $ are anchors (start and end respectively). These cause your regex to explicitly match an entire string which starts with : has anything between it and ends with :.
If you want to match characters within a string you can remove the anchors.
Your * indicates zero or more so you'll be matching :: as well. It'll be better to change this to + which means one or more. In fact if you're just looking for text you may want to use a range [a-z0-9] with a case insensitive modifier.
If we put it all together we'll have regex like this /:([a-z0-9]+):/gmi
match a string beginning with : with any alphanumeric character one or more times ending in : with the modifiers g globally, m multi-line and i case insensitive for things like :FacePalm:.
Using it in JavaScript we can end up with:
var mytext = 'Hello :smile: and jolly :wave:';
var matches = mytext.match(/:([a-z0-9]+):/gmi);
// matches = [':smile:', ':wave:'];
You'll have an array with each match found.
I have the following RegEx:
[!?\.](.*)\.example\.com
and this sample string:
test foo abc.def.example.com bar ghi.jkl.example.com def
I want that the RegEx products the following matches: def.example.com and jkl.example.com.
What do I have to change? Should be working on all subdomains of example.com. If possible it should only take the first subdomain-level (abc.def.example.com -> def.example.com).
Tested it on regexpal, not fully working :(
You may use the following expression : [^.\s]+\.example\.com.
Explanation
[^.\s]+ : match anything except a dot or whitespace one or more times
\.example\.com : match example.com
Note that you don't need to escape a dot in a character class
Just on a side note, while HamZa's answer works for your current sample code, if you need to make sure that the domain names are also valid, you might want to try a different approach, since [^.\s]+ will match ANY character that is not a space or a . (for example, that regex will match jk&^%&*(l.example.com as a "valid" subdomain).
Since there are far fewer valid characters for domain name values than there are invalid ones, you might consider using an "additive" approach to the regex, rather than subtractive. This pattern here is probably the one that you are looking for for valid domain names: /(?:[\s.])([a-z0-9][a-z0-9-]+[a-z0-9]\.example\.com)/gi
To break it down a little more . . .
(?:[\s.]) - matches the space or . that would mark the beginning of the loweset level subdomain
([a-z0-9][a-z0-9-]+[a-z0-9]\.example\.com) - this captures a group of letters, numbers or dashes, that must begin and end with a letter or a number (domain name rules), and then the example.com domain.
gi - makes the regex pattern greedy and case insensitive
At this point, it simply a question of grabbing the matches. Since .match() doesn't play well with the regex "non-capturing groups", use .exec() instead:
var domainString = "test foo abc.def.example.com bar ghi.jkl.example.com def";
var regDomainPattern = /(?:[\s.])([a-z0-9][a-z0-9-]+[a-z0-9]\.example\.com)/gi;
var aMatchedDomainStrings = [];
var patternMatch;
// loop through as long as .exec() still gets a match, and take the second index of the result (the one that ignores the non-capturing groups)
while (null != (patternMatch = regDomainPattern.exec(domainString))) {
aMatchedDomainStrings.push(patternMatch[1]);
}
At that point aMatchedDomainStrings should contain all of your valid, first-level, sub-domains.
var domainString = "test foo abc.def.example.com bar ghi.jkl.example.com def";
. . . should get you: def.example.com and jkl.example.com, while:
var domainString = "test foo abc.def.example.com bar ghi.jk&^%&*(l.example.com def";
. . . should get you only: def.example.com
I am trying to validate a string, that should contain letters numbers and special characters &-._ only. For that I tried with a regular expression.
var pattern = /[a-zA-Z0-9&_\.-]/
var qry = 'abc&*';
if(qry.match(pattern)) {
alert('valid');
}
else{
alert('invalid');
}
While using the above code, the string abc&* is valid. But my requirement is to show this invalid. ie Whenever a character other than a letter, a number or special characters &-._ comes, the string should evaluate as invalid. How can I do that with a regex?
Add them to the allowed characters, but you'll need to escape some of them, such as -]/\
var pattern = /^[a-zA-Z0-9!##$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]*$/
That way you can remove any individual character you want to disallow.
Also, you want to include the start and end of string placemarkers ^ and $
Update:
As elclanrs understood (and the rest of us didn't, initially), the only special characters needing to be allowed in the pattern are &-._
/^[\w&.\-]+$/
[\w] is the same as [a-zA-Z0-9_]
Though the dash doesn't need escaping when it's at the start or end of the list, I prefer to do it in case other characters are added. Additionally, the + means you need at least one of the listed characters. If zero is ok (ie an empty value), then replace it with a * instead:
/^[\w&.\-]*$/
Well, why not just add them to your existing character class?
var pattern = /[a-zA-Z0-9&._-]/
If you need to check whether a string consists of nothing but those characters you have to anchor the expression as well:
var pattern = /^[a-zA-Z0-9&._-]+$/
The added ^ and $ match the beginning and end of the string respectively.
Testing for letters, numbers or underscore can be done with \w which shortens your expression:
var pattern = /^[\w&.-]+$/
As mentioned in the comment from Nathan, if you're not using the results from .match() (it returns an array with what has been matched), it's better to use RegExp.test() which returns a simple boolean:
if (pattern.test(qry)) {
// qry is non-empty and only contains letters, numbers or special characters.
}
Update 2
In case I have misread the question, the below will check if all three separate conditions are met.
if (/[a-zA-Z]/.test(qry) && /[0-9]/.test(qry) && /[&._-]/.test(qry)) {
// qry contains at least one letter, one number and one special character
}
Try this regex:
/^[\w&.-]+$/
Also you can use test.
if ( pattern.test( qry ) ) {
// valid
}
let pattern = /^(?=.*[0-9])(?=.*[!##$%^&*])(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9!##$%^&*]{6,16}$/;
//following will give you the result as true(if the password contains Capital, small letter, number and special character) or false based on the string format
let reee =pattern .test("helLo123#"); //true as it contains all the above
I tried a bunch of these but none of them worked for all of my tests. So I found this:
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?!.*\s).{8,15}$
from this source: https://www.w3resource.com/javascript/form/password-validation.php
Try this RegEx: Matching special charecters which we use in paragraphs and alphabets
Javascript : /^[a-zA-Z]+(([\'\,\.\-_ \/)(:][a-zA-Z_ ])?[a-zA-Z_ .]*)*$/.test(str)
.test(str) returns boolean value if matched true and not matched false
c# : ^[a-zA-Z]+(([\'\,\.\-_ \/)(:][a-zA-Z_ ])?[a-zA-Z_ .]*)*$
Here you can match with special char:
function containsSpecialChars(str) {
const specialChars = /[`!##$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/;
return specialChars.test(str);
}
console.log(containsSpecialChars('hello!')); // 👉️ true
console.log(containsSpecialChars('abc')); // 👉️ false
console.log(containsSpecialChars('one two')); // 👉️ false