Regular expression in MVC using JavaScript - javascript

here is the format of my regular expression:
#"^PR[a-zA-Z0-9-]{36}[0-9]{2}([a-zA-Z0-9-]{3}2[a-zA-Z0-9-]{12}){2,10}$".
There should be separate validation for each condition. So I succeeded for first three conditions using JavaScript sub-string. Just stuck for last condition i.e.
"([a-zA-Z0-9-]{3}2[a-zA-Z0-9-]{12}){2,10}".
In this, I want to check every fourth character must be "2".
How do i achieve this by JavaScript?

If you have the full regex, why not just use it as a whole:
var regex = /^PR[a-zA-Z0-9-]{36}[0-9]{2}([a-zA-Z0-9-]{3}2[a-zA-Z0-9-]{12}){2,10}$/;
var str = "PR12345678901234567890123456789012345600AAA2BBBCCCDDDEEEaaa2bbbcccdddeee";
console.log(regex.test(str)); // true
But if you must really break it, you could do:
var regex1 = /^PR[a-zA-Z0-9-]{36}$/;
console.log(regex1.test(str.substring(0,38))); // true
var regex2 = /^[0-9]{2}$/;
console.log(regex2.test(str.substring(38,40))); // true
var regex3 = /^([a-zA-Z0-9-]{3}2[a-zA-Z0-9-]{12}){2,10}$/;
console.log(regex3.test(str.substring(40,str.length))); // true
See demo fiddle here.
Edit:
To check whether every fourth character must be two, use:
var regexfourth = /^([a-zA-Z0-9-]{3}2)+$/;
console.log(regexfourth.test("aaa2bbb2ccc2ddd2")); // true
console.log(regexfourth.test("aaa2bbb2ccc3ddd2")); // false(notice a 3 after ccc)
Demo fiddle for this here (check the bottom).

Related

Regular Expressions: AND behavior

I'm studying regular expressions in Javascript
I've seen many ways to do exclusive matching through the OR operator with [] and | within groups ().
I can't understand how to achieve the AND behavior with regular expressions. I've done some research but I didn't find what I need.
Here an example. I have the following string: kata. I want to compare it with another string: steak. The goal is to return true if all the letters in steak is contained in kata. If I use this regular expression [steak] it returns true but actually it should return false because in kata there is no "s".
Example 2. String1 = scriptsjava, string2 = javascript, result = true (because string2 is contained in string1)
Example 3. String1 = jscripts, string2 = javascript, result = false (because string2 is not fully contained in string1)
Example 4. String1 = rkqodlw, string2 = world, result = true (because the string world is in the first string)
I thought that using regular expressions is the best way and I considered string2 as a pattern. My solution to this problem is the following
var validate=true;
var counter = 0;
str2.split("").map(val => {
counter++;
var char = new RegExp(val);
if (char.test(str1) === false) { validate = false;} else
{
str1 = str1.slice(0, counter+1) + str1.slice(counter+1,str1.length);
console.log(str1);
}
});
return validate;
I think is not the most efficient though. Do you have a better solution for this?
You want a set comparison, specifically a superset check. Simple with a Set:
let s1 = 'javascript';
let s2 = 'scriptsjava';
Set.prototype.isSuperset = function(subset) {
for (var elem of subset) {
if (!this.has(elem)) {
return false;
}
}
return true;
}
console.log(new Set(s1).isSuperset(new Set(s2)));
Well this is my second answer, I might remove the previous answer later on, if I see this seems to be helpful for you.
Although there are some good answer being posted but yet as I can see that you want to have a hold on AND operation in regex, therefore you want a regexAND answer. Thus I am going to give you an answer that works according to your need. But if you want me to be frank, then I would say, for your requirement , regex operation is kind of the last option that I would want to go for.
Now comes the answer:
For each pair , say str1, and str2. You want to see if each character of str2 is present in str1.
thus you can make AND operation in the form of positive lookahead for each character for the entire string of str2 and see if all these exists in str1 or not.
each positie lookahead would look likhe this: (?=.*w)
when written one beside another like the regex mentioned bellow they work as AND.
For example:
str1="rkqodlw"
str2="world"
make a regex by str2 in the following way:
^(?=.*w)(?=.*o)(?=.*r)(?=.*l)(?=.*d).*$
and see if that matches with str1
like this way:
function compare(str1,str2)
{
var regexAnd=str2.split("").join(")(?=.*");
var regexStr="^"+"(?=.*"+regexAnd+").*$";
console.log(regexStr); // prints the entire and condition
var re = new RegExp(regexStr,"gm");
return re.test(str1);
}
console.log(compare("scriptsjava","javascript"));
console.log(compare("jscripts","javascript"));
console.log(compare("rkqodlw","world"));

Whats wrong with this regex logic

I am trying to fetch the value after equal sign, its works but i am getting duplicated values , any idea whats wrong here?
// Regex for finding a word after "=" sign
var myregexpNew = /=(\S*)/g;
// Regex for finding a word before "=" sign
var mytype = /(\S*)=/g;
//Setting data from Grid Column
var strNew = "QCById=20";
var matchNew = myregexpNew.exec(strNew);
var newtype = mytype.exec(strNew);
alert(matchNew);
https://jsfiddle.net/6vjjv0hv/
exec returns an array, the first element is the global match, the following ones are the submatches, that's why you get ["=20", "20"] (using console.log here instead of alert would make it clearer what you get).
When looking for submatches and using exec, you're usually interested in the elements starting at index 1.
Regarding the whole parsing, it's obvious there are better solution, like using only one regex with two submatches, but it depends on the real goal.
You can try without using Regex like this:
var val = 'QCById=20';
var myString = val.substr(val.indexOf("=") + 1);
alert(myString);
Presently exec is returning you the matched value.
REGEXP.exec(SOMETHING) returns an array (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).
The first item in the array is the full match and the rest matches the parenthesized substrings.
You do not get duplicated values, you just get an array of a matched value and the captured text #1.
See RegExp#exec() help:
If the match succeeds, the exec() method returns an array and updates properties of the regular expression object. The returned array has the matched text as the first item, and then one item for each capturing parenthesis that matched containing the text that was captured.
Just use the [1] index to get the captured text only.
var myregexpNew = /=(\S*)/g;
var strNew = "QCById=20";
var matchNew = myregexpNew.exec(strNew);
if (matchNew) {
console.log(matchNew[1]);
}
To get values on both sides of =, you can use /(\S*)=(\S*)/g regex:
var myregexpNew = /(\S*)=(\S*)/g;
var strNew = "QCById=20";
var matchNew = myregexpNew.exec(strNew);
if (matchNew) {
console.log(matchNew[1]);
console.log(matchNew[2]);
}
Also, you may want to add a check to see if the captured values are not undefined/empty since \S* may capture an empty string. OR use /(\S+)=(\S+)/g regex that requires at least one non-whitespace character to appear before and after the = sign.

Why do these JavaScript regular expression capture parenthesis snag entire line instead of the suffixes appended to a word?

Can someone please tell me WHY my simple expression doesn't capture the optional arbitrary length .suffix fragments following hello, matching complete lines?
Instead, it matches the ENTIRE LINE (hello.aa.b goodbye) instead of the contents of the capture parenthesis.
Using this code (see JSFIDDLE):
//var line = "hello goodbye"; // desired: suffix null
//var line = "hello.aa goodbye"; // desired: suffix[0]=.aa
var line = "hello.aa.b goodbye"; // desired: suffix[0]=.aa suffix[1]=.b
var suffix = line.match(/^hello(\.[^\.]*)*\sgoodbye$/g);
I've been working on this simple expression for OVER three hours and I'm beginning to believe I have a fundamental misunderstanding of how capturing works: isn't there a "cursor" gobbling up each line character-by-character and capturing content inside the parenthesis ()?
I originally started from Perl and then PHP. When I started with JavaScript, I got stuck with this situation once myself.
In JavaScript, the GLOBAL match does NOT produce a multidimensional array. In other words, in GLOBAL match there is only match[0] (no sub-patterns).
Please note that suffix[0] matches the whole string.
Try this:
//var line = "hello goodbye"; // desired: suffix undefined
//var line = "hello.aa goodbye"; // desired: suffix[1]=.aa
var line = "hello.aa.b goodbye"; // desired: suffix[1]=.aa suffix[2]=.b
var suffix = line.match(/^hello(\.[^.]+)?(\.[^.]+)?\s+goodbye$/);
If you have to use a global match, then you have to capture the whole strings first, then run a second RegEx to get the sub-patterns.
Good luck
:)
Update: Further Explanation
If each string only has ONE matchable pattern (like var line = "hello.aa.b goodbye";)
then you can use the pattern I posted above (without the GLOBAL modifier)
If a sting has more than ONE matchable pattern, then look at the following:
// modifier g means it will match more than once in the string
// ^ at the start mean starting with, when you wan the match to start form the beginning of the string
// $ means the end of the string
// if you have ^.....$ it means the whole string should be a ONE match
var suffix = line.match(/^hello(\.[^.]+)?(\.[^.]+)?\s+goodbye$/g);
var line = 'hello.aa goodbye and more hello.aa.b goodbye and some more hello.cc.dd goodbye';
// no match here since the whole of the string doesn't match the RegEx
var suffix = line.match(/^hello(\.[^.]+)?(\.[^.]+)?\s+goodbye$/);
// one match here, only the first one since it is not a GLOBAL match (hello.aa goodbye)
// suffix[0] = hello.aa goodbye
// suffix[1] = .aa
// suffix[2] = undefined
var suffix = line.match(/hello(\.[^.]+)?(\.[^.]+)?\s+goodbye/);
// 3 matches here (but no sub-patterns), only a one dimensional array with GLOBAL match in JavaScript
// suffix[0] = hello.aa goodbye
// suffix[1] = hello.aa.b goodbye
// suffix[2] = hello.cc.dd goodbye
var suffix = line.match(/hello(\.[^.]+)?(\.[^.]+)?\s+goodbye/g);
I hope that helps.
:)
inside ()
please do not look for . and then some space , instead look for . and some characters and finally outside () look for that space
A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations.
var suffix = line.match(/^hello((\.[^\.]*)*)\sgoodbye$/g);
if (suffix !== null)
suffix = suffix[1].match(/(\.[^\.\s]*)/g)
and I recommand regex101 site.
Using the global flag with the match method doesn't return any capturing groups. See the specification.
Although you use ()* it's only one capturing group. The * only defines that the content has to be matched 0 or more time before the space comes.
As #EveryEvery has pointed out you can use a two-step approach.

javascript regExp check last character

I'm using this RexExp code var userIdPattern = new RegExp('^([A-z0-9_.]{4,15})$');, I want to check if last character was dot (.) then .test() returns me false:
var userIdPattern = new RegExp('^([A-z0-9_.]{4,15})$');
console.log(userIdPattern.test('Omid.my.')); // -> I need this to be false
and in this case return me true:
userIdPattern.test('Omid.my'); //-> true
Following the update, a more appropriate regex might be:
var userIdPattern = new RegExp('^([A-Za-z0-9\[\]\\^`][A-z0-9_.]{2,13}[A-Za-z0-9\[\]\\^`])$');
That is, if you want to include other special characters in the usernames like 7stud mentioned in his comment and only exclude . and _ from the first and last characters.
Otherwise, to prevent those characters, I would suggest:
var userIdPattern = new RegExp('^([A-Za-z0-9][A-Za-z0-9_.]{2,13}[A-Za-z0-9])$');
Fiddle to test.
You can make it like this
^([A-z0-9_.]{3,14}[A-z0-9])$
Edit after reading your comment
^[a-z0-9][a-z0-9_.]{2,13}[a-z0-9]$
Preview
Also I suggest you use flag the i to ignore case:
var userIdPattern = new RegExp('^[a-z0-9][a-z0-9_.]{3,13}[a-z0-9]$', 'i');

Regex test function do not return the same depending quotes

I have a weird case with a regular expression in javascript:
var re = /[^\s]+(?:\s+|$)/g;
re.test('foo'); // return true
re.test("foo"); // return false
Is a regular expression type sensitive? My first goal is to extract all word (separated by one or more whitespace) of a string.
Thanks for your help.
Julien
When using the g flag on a Javascript regular expression, it will keep track of where the last match was found and start searching from that index the next time you try to find a match.
Between the two re.test() calls, take a look at re.lastIndex to see what I am talking about.
For example:
var re = /[^\s]+(?:\s+|$)/g;
re.test('foo'); // return true
re.lastIndex; // 3
re.test("foo"); // return false
You will notice that the type of quotes you use does not matter, re.test('foo'); re.test('foo'); will have the same behavior.
If you want the regex to start fresh, you can either remove the global flag from your regex or set re.lastIndex to 0 after each attempt to find a match, for example:
var re = /[^\s]+(?:\s+|$)/g;
re.test('foo'); // return true
re.lastIndex = 0;
re.test("foo"); // return true
The alternating noted by Blender in comments can be explained because lastIndex is automatically set to 0 when a match fails, so the next attempt after the failure will succeed.

Categories