.match() with a regular expression returns null - javascript

I am trying to do something I thought would be pretty easy to do, which is to restrict a string to certain characters by matching a regular expression.
var value = 'FailureStr1ng';
var type = 'ALPHA';
var regex = null;
switch(type) {
case 'ALPHA':
regex = '^[a-zA-Z]+$';
break;
case 'NUMERIC':
regex = '^[0-9]+$';
break;
case 'ALPHANUMERIC':
regex = '^[a-zA-Z0-9]+$';
break;
}
return value.match(regex);
For some reason, when using the match it always returns null. Is there a way to fix this, or a better method to do this?
Note: The code here is a snippet of much larger code, and in turn the value and type variable are usually defined by another method.

You want RegExp.test, which tests a value for a match instead of retrieving the match. With your existing code, that would mean:
if(!new RegExp(regex).test(value)){
alert('Your string was invalid.');
}
However, it would be preferable to use RegExp literals instead of strings, as they're much more efficient and clear, and less prone to error:
var value = 'FailureStr1ng';
var type = 'ALPHA';
var regex = null;
switch(type) {
case 'ALPHA':
regex = /^[a-zA-Z]+$/;
break;
case 'NUMERIC':
regex = /^[0-9]+$/;
break;
case 'ALPHANUMERIC':
regex = /^[a-zA-Z0-9]+$/;
break;
}
if(!regex.test(value)) {
alert('Your string was invalid.');
}
Even better, use a dictionary:
var expressions = {
ALPHA: /^[a-zA-Z]+$/,
NUMERIC: /^[0-9]+$/,
ALPHANUMERIC: /^[a-zA-Z0-9]+$/
};
if(!expressions[type].test(value)) {
alert('Your string was invalid.');
}

Regex must be surrounded with /, not ', so that JavaScript creates a variable of type regex, not of type string. So for instance, for your ALPHA case, you should have
regex = /^[a-zA-Z]+$/;
See MDN's page on .match for more information about using .match.

Your code looks like it's inside a function { ... }. Are you returning anything? If not, that's why you're getting null back...
Also, regexes are surrounded by slashes (/.../), not quotes.

Related

Regular Expression Returns Undefined

I'm attempting one of the beginner coderByte challenges, Simple Symbols. Challenge summary below.
"Using the JavaScript language, have the function SimpleSymbols(str) take the str parameter being passed and determine if it is an acceptable sequence by either returning the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter."
function SimpleSymbols(str){
var RegExp = /\+\w\+/gi;
var regexp1 = /^\w/gi;
var regexp2 = /\w$/g;
if(regexp1.test(str) == true){
return false
} else if(regexp2.test(str) == true){
return false
} else if(RegExp == true){
return true
}
}
console.log(SimpleSymbols('+d+=3=+s+'));
console.log(SimpleSymbols('f++d+'));
The first regular expression I'm testing, /^\w/gi, comes back undefined, and I can't figure out why?
https://regex101.com/ is a great tool I've used before, and my expression does identify f as the first character in the string, but when I test it in codepen, it comes back undefined in the console.
Code
See regex in use here
^[+=\d]*\+(?:[a-z]\+[+=\d]*)+$
Alternatively, using the opposite logic (catching invalid strings instead of valid ones), you can use (?:^|[^+])[a-z]|[a-z](?:[^+]|$)
Usage
Please note the valid/invalid strings below have been created according to the OP's explanation of valid and invalid strings: That each letter must be surrounded by a + symbol. and that the plus sign + may be shared between characters such that +a+a+ is valid (specified in comments below the question).
var a = [
// valid
"++d+===+c++==+a++",
"+a+a+a+",
"+a++a+",
"+a+",
// invalid
"++d+===+c++==a",
"+=d+",
"+dd+",
"+d=+",
"+d+d",
"d+d+"
];
var r = /^[+=\d]*\+(?:[a-z]\+[+=\d]*)+$/mi;
a.forEach(function(s){
console.log(r.test(s));
});
Explanation
^ Assert position at the start of the line
[+=\d]* Match any number of characters in the set (+, =, or digit)
\+ Match a literal plus sign +
(?:[a-z]\+[+=\d]*)+ Match one or more of the following
[a-z] Match a lowercase ASCII letter
\+ Match a literal plus sign +
[+=\d]* Match any number of characters in the set (+, =, or digit)
$ Assert position at the end of the line
It's returning undefined because your expression does not meet any of the criteria. Since you have no else {} defined, than nothing gets returned. Thus you get undefined. Try this:
function SimpleSymbols(str){
var RegExp = /\+\w\+/gi;
var regexp1 = /^\w/gi;
var regexp2 = /\w$/g;
if(regexp1.test(str) == true){
return false
} else if(regexp2.test(str) == true){
return false
} else if(RegExp == true){
return true
} else {
return "catch all here";
}
}
console.log(SimpleSymbols('+d+=3=+s+'));
console.log(SimpleSymbols('f++d+'));
You can use a single regex and the string.test() method (which returns just true/false).
Below are 2 different ways (regex) to do it .
First requires a separate + between word chars. Example +a++b+ (true)
^
(?: [+=]* \+ \w \+ [+=]* )+
$
Second can take a common + between word chars. Example +a+b+ (true)
^
(?:
[+=]* \+ \w
(?= \+ )
)+
[+=]*
$
var patt1 = new RegExp("^(?:[+=]*\\+\\w\\+[+=]*)+$");
function SimpleSymbols_1(str){
return patt1.test(str);
}
var patt2 = new RegExp("^(?:[+=]*\\+\\w(?=\\+))+[+=]*$");
function SimpleSymbols_2(str){
return patt2.test(str);
}
console.log(SimpleSymbols_1('+d+=3=+s+'));
console.log(SimpleSymbols_1('f++d+'));
console.log(SimpleSymbols_1('+a+b+c+'));
console.log(SimpleSymbols_2('+a+b+c+'));
console.log(SimpleSymbols_2('+a+=+c+'));
console.log(SimpleSymbols_2('+a++c+'));
Thank you all for throwing some support/comments my way. Again, I am new to JavaScript and Regular Expressions are fairly foreign to me, though I am gaining some traction in understanding them. Here is the updated solution I posted. It's quite convoluted and perhaps a more inelegant and non-simple way to come to the right answer, but it worked.
function SimpleSymbols(str){
var RegExp = /\+[a-z]\+/gi;
var regexp1 = /^[a-z]/gi;
var regexp2 = /[a-z]$/g;
var regexp3 = /[a-z]\=/gi;
var regexp4 = /\=[a-z]/gi;
if(regexp1.test(str) === true){
return false
} else if(regexp2.test(str) === true){
return false
} else if(regexp3.test(str) === true){
return false
} else if(regexp4.test(str) === true){
return false
} else {
return true
}
}
console.log(SimpleSymbols('+d+=3=+s+'));
console.log(SimpleSymbols('f++d+'));
console.log(SimpleSymbols('+d===+a+'));
console.log(SimpleSymbols('+a='));
console.log(SimpleSymbols('2+a+a+'));
console.log(SimpleSymbols('==a+'));
I was sure there had to be a way to use only one regular expression, but again, I'm still very much a novice.
Thanks again everyone.

Switch/case not responding after string.split()

I am trying to solve a problem, where the function accepts a string, always in lowercase, and then takes the first letter and adds it to the back of the string.
It does not seem to be working.
var fir;
function convert(str) {
str = str.split("");
fir = str[0];
str = str.join("");
switch (fir) {
case /[bcdfghjklmnpqrstvwxyz]/.test(fir):
var ind = str.substr(1);
str = ind + str[0];
break;
}
return str;
}
If I call convert("pig"); from another part of my javascript then it should return "igp"
I think this is all you need which does what you asked for - " function accepts a string, always in lowercase, and then takes the first letter and adds it to the back of the string".
function convert(str) {
str = str.substr(1) + str[0];
return str;
}
convert("pig");
If you are insistent on using what you have, I have fixed it here.
var fir;
function convert(str) {
str = str.split("");
fir = str[0];
str = str.join("");
switch (true) {
case /[bcdfghjklmnpqrstvwxyz]/.test(fir):
var ind = str.substr(1);
str = ind + str[0];
break;
}
return str;
}
convert("pig");
The only change I have done is changing switch(fir) to switch(true) which is why your switch case wasn't working.
I think you should read about the Javascript String Reference.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
Remember:
The other way (introduced in ECMAScript 5) is to treat the string as an array-like object, where individual characters correspond to a numerical index:
Now, after reading the JS String Reference. We can do something even more smart concatenating the sliced string array without the 0 index letter with the last letter of the string array.
That way you could do something without regular expressions, switch and other stuff.
Remember to always read the references about the Global Objects, it could easy save you a lot of work and get better understand of the JS Language
Example code:
function convert(string){
return string.slice(1) + string[0];
}
Your switch statement is incorrect. Your case expression case /[bcdfghjklmnpqrstvwxyz]/.test(fir) evaluates to a boolean value while in switch expression you are passing a character in fir variable (as str[0] = 'p') which is a mismatch. So your case statement will never get executed and it will come out of switch block without doing anything. Change it to switch(true) and you should be good.

Three Char Month and Culture matching in javascript

I have a multi cultural website, where I allow users to enter values in a dd-MMM-yyyy format. I am able to determine the different values based upon their culture in C# (May, English = May, German = Mai)
the problem I am having is the javascript validation of these months. I am able to build the list of acceptable values:
english:
^Jan$|^Feb$|^Mar$|^Apr$|^May$|^Jun$|^Jul$|^Aug$|^Sep$|^Oct$|^Nov$|^Dec$
German:
^Jan$|^Feb$|^Mrz$|^Apr$|^Mai$|^Jun$|^Jul$|^Aug$|^Sep$|^Okt$|^Nov$|^Dez$
I just want to make this regular expression case insensitive. but all the references I see are all pointing me to the /gi flag, but I all of the examples make no sense. I have tried the following and it just doesn't work:
var shouldMatch = "may";
var regexPattern = "^Jan$|^Feb$|^Mar$|^Apr$|^May$|^Jun$|^Jul$|^Aug$|^Sep$|^Oct$|^Nov$|^Dec$/gi"
if(shouldMatch.match(regexPattern) != null) {
//this should happen
}
What am I doing wrong? the regex help out there for javascript is killing me.
jsFiddle Demo
But what about trying to match "mAR" or "MAr", etc.? This quickly becomes an interesting scenario. In my opinion, an easy way to do this is to just match to upper case
var shouldMatch = "May";
var regexPattern = "^JAN$|^FEB$|^MAR$|^APR$|^MAY$|^JUN$|^JUL$|^AUG$|^SEP$|^OCT$|^NOV$|^DEC$";
if(shouldMatch.toUpperCase().match(regexPattern) != null) {
alert("match");
}
regexPattern is a string, not a regular expression.
Convert it to a RegExp before you use it with match:
var regexPattern = new RegExp("^JAN$|^FEB$|^MAR$|^APR$|^MAY$|^JUN$|^JUL$|^AUG$|^SEP$|^OCT$|^NOV$|^DEC$", "gi");
And also, convert the shouldMatch to upper case before you use it:
shouldMatch = shouldMatch.toUpperCase();
Your regular expression should not be a string:
var shouldMatch = "may";
var regexPattern = /^Jan$|^Feb$|^Mar$|^Apr$|^May$|^Jun$|^Jul$|^Aug$|^Sep$|^Oct$|^Nov$|^Dec$/i;
if(shouldMatch.match(regexPattern) != null) {
// this seems happened
}
This should work for you.
Changed to using test
No need for the global "g" flag as you are testing the whole string from beginning "^" to end "$"
Changed string regexPattern into a RegExp object
The "i" flag is needed because you want case insensitive.
Javascript
var shouldMatch = "may";
var regexPattern = /^Jan$|^Feb$|^Mar$|^Apr$|^May$|^Jun$|^Jul$|^Aug$|^Sep$|^Oct$|^Nov$|^Dec$/i;
if(regexPattern.test(shouldMatch)) {
alert(shouldMatch);
}
On jsfiddle
You could also make it a little shorter and a little less ugly by doing this
var regexPattern = /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$/i;
On jsfiddle
As an alternative to regex, you could also use String.indexOf and Array.some, and try each pattern to see if it is in the string you are testing. This example will require a modern browser or a "shim"/"polyfill" for older browsers. You could also check equality "===" if you want to match the whole string rather than see if it is contained in.
Javascript
var shouldMatch = "may";
var patterns = "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec".split("|");
var matched = patterns.some(function (pattern) {
if (shouldMatch.toLowerCase().indexOf(pattern.toLowerCase()) !== -1) {
alert(shouldMatch);
return true;
}
return false;
});
On jsfiddle
Or run the possibilities together-
var Rx=/^(jan|feb|m(ar|rz)|apr|ma[iy]|jun|jul|aug|sep|o[ck]t|nov|de[cz])$/i
Rx.test('may');

Javascript IndexOf with integers in string not working

Can anyone tell me why does this not work for integers but works for characters? I really hate reg expressions since they are cryptic but will if I have too. Also I want to include the "-()" as well in the valid characters.
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
Review
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
This String "method" returns true if str is contained within itself, e.g. 'hello world'.indexOf('world') != -1would returntrue`.
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
The value of $('#textbox1').val() is already a string, so the .toString() isn't necessary here.
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
This is where it goes wrong; effectively, this executes '1234'.indexOf('0123456789') != -1; it will almost always return false unless you have a huge number like 10123456789.
What you could have done is test each character in str whether they're contained inside '0123456789', e.g. '0123456789'.indexOf(c) != -1 where c is a character in str. It can be done a lot easier though.
Solution
I know you don't like regular expressions, but they're pretty useful in these cases:
if ($("#textbox1").val().match(/^[0-9()]+$/)) {
alert("valid");
} else {
alert("not valid");
}
Explanation
[0-9()] is a character class, comprising the range 0-9 which is short for 0123456789 and the parentheses ().
[0-9()]+ matches at least one character that matches the above character class.
^[0-9()]+$ matches strings for which ALL characters match the character class; ^ and $ match the beginning and end of the string, respectively.
In the end, the whole expression is padded on both sides with /, which is the regular expression delimiter. It's short for new RegExp('^[0-9()]+$').
Assuming you are looking for a function to validate your input, considering a validChars parameter:
String.prototype.validate = function (validChars) {
var mychar;
for(var i=0; i < this.length; i++) {
if(validChars.indexOf(this[i]) == -1) { // Loop through all characters of your string.
return false; // Return false if the current character is not found in 'validChars' string.
}
}
return true;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.validate(validChars)) {
alert("Only valid characters were found! String validates!");
} else {
alert("Invalid Char found! String doesn't validate.");
}
However, This is quite a load of code for a string validation. I'd recommend looking into regexes, instead. (Jack's got a nice answer up here)
You are passing the entire list of validChars to indexOf(). You need to loop through the characters and check them one-by-one.
Demo
String.prototype.Contains = function (str) {
var mychar;
for(var i=0; i<str.length; i++)
{
mychar = this.substr(i, 1);
if(str.indexOf(mychar) == -1)
{
return false;
}
}
return this.length > 0;
};
To use this on integers, you can convert the integer to a string with String(), like this:
var myint = 33; // define integer
var strTest = String(myint); // convert to string
console.log(strTest.Contains("0123456789")); // validate against chars
I'm only guessing, but it looks like you are trying to check a phone number. One of the simple ways to change your function is to check string value with RegExp.
String.prototype.Contains = function(str) {
var reg = new RegExp("^[" + str +"]+$");
return reg.test(this);
};
But it does not check the sequence of symbols in string.
Checking phone number is more complicated, so RegExp is a good way to do this (even if you do not like it). It can look like:
String.prototype.ContainsPhone = function() {
var reg = new RegExp("^\\([0-9]{3}\\)[0-9]{3}-[0-9]{2}-[0-9]{2}$");
return reg.test(this);
};
This variant will check phones like "(123)456-78-90". It not only checks for a list of characters, but also checks their sequence in string.
Thank you all for your answers! Looks like I'll use regular expressions. I've tried all those solutions but really wanted to be able to pass in a string of validChars but instead I'll pass in a regex..
This works for words, letters, but not integers. I wanted to know why it doesn't work for integers. I wanted to be able to mimic the FilteredTextBoxExtender from the ajax control toolkit in MVC by using a custom Attribute on a textBox

Validating alphabetic only string in javascript

How can I quickly validate if a string is alphabetic only, e.g
var str = "!";
alert(isLetter(str)); // false
var str = "a";
alert(isLetter(str)); // true
Edit : I would like to add parenthesis i.e () to an exception, so
var str = "(";
or
var str = ")";
should also return true.
Regular expression to require at least one letter, or paren, and only allow letters and paren:
function isAlphaOrParen(str) {
return /^[a-zA-Z()]+$/.test(str);
}
Modify the regexp as needed:
/^[a-zA-Z()]*$/ - also returns true for an empty string
/^[a-zA-Z()]$/ - only returns true for single characters.
/^[a-zA-Z() ]+$/ - also allows spaces
Here you go:
function isLetter(s)
{
return s.match("^[a-zA-Z\(\)]+$");
}
If memory serves this should work in javascript:
function containsOnlyLettersOrParenthesis(str)
(
return str.match(/^([a-z\(\)]+)$/i);
)
You could use Regular Expressions...
functions isLetter(str) {
return str.match("^[a-zA-Z()]+$");
}
Oops... my bad... this is wrong... it should be
functions isLetter(str) {
return "^[a-zA-Z()]+$".test(str);
}
As the other answer says... sorry

Categories