I've been trying evaluate a string based in a regular expression, however I noticed a weird behaviour and when I test with the regular expression more than once. The test method alternates between true and false .
Check this codepen --> http://codepen.io/gpincheiraa/pen/BoXrEz?editors=001
var emailRegex = /^([a-zA-Z0-9_\.\-]){0,100}\#(([a-zA-Z0-9\-]){0,100}\.)+([a-zA-Z0-9]{2,4})+$/,
phoneChileanRegex = /^\+56\S*\s*9\S*\s*\d{8}(?!\#\w+)/g,
number = "+56982249953";
if(!number.match(phoneChileanRegex) && !number.match(emailRegex) ) {
console.log("it's not a phone number or email address");
}
//Weird Behaviour
console.log(phoneChileanRegex.test(number)); --> true
console.log(phoneChileanRegex.test(number)); --> false
From the MDN documentation:
As with exec() (or in combination with it), test() called multiple times on the same global regular expression instance will advance past the previous match.
So, the second time you call the method, it will look for a match after the first match, i.e. after +56982249953. There is no match because the pattern is anchored to the start of the string (^) (and because there are no characters left), so it returns false.
To make this work you have to remove the g modifier.
That's because the test method, like many RegExp methods, tries to find multiple matches in the same string when used with the g flag. To do this, it keeps track of position it should search from in the RegExp's lastIndex property. If you don't need to find multiple matches, just don't put the g flag. And if you ever want to use it, just remember to set regex.lastIndex to 0 when you want to test a new string.
Read more about lastIndex on MDN
Related
I think this is a very basic question, but I really can't understand the concept. I have the following regular expression:
var t = '11:59 am';
t.match(/^(\d+)/);
Now, according to my understanding when I print the value I should just get 11 since I am just checking for digits. However, I get 11,11. I have to use 0th element to pick the required value like t.match(/^(\d+)/)[0].
This is because you are using a capture group, (), around the digits. Try replacing this with:
t.match(/^\d+/);
Note: this will still return an array, because that's just what .match() does.
match() always returns an array if there are any matches. Element [0] is the whole match, and element [1] is what is inside the first set of parentheses.
Here is the output from my browsers console. This regex checks for doubled_words, looks for occurrences of words (strings containing 1 or more letters) followed by whitespace followed by the same word.
var reg=/([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1/gi;
undefined
reg.test("sdfs sdsdf")
true
reg.test("sdfs sdsdf")
false
the result is true alternate times, why is this weird behavior?
That behavior is due to use of global flag. Remove it
var reg=/([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1/;
Using g causes regex state (lastIndex value) to be remembered across multipel calls to test or exec methods.
Check this official reference Read the Description section.
Today I was messing around with Javascript regexp's and found out this:
//Suppose
var one = 'HELLOxBYE';
var two = 'HELLOBYE';
You could create a regex that tries to capture the 'x' in both of these ways:
/^HELLO(x?)BYE$/ //(A)
//or
/^HELLO(x)?BYE$/ //(B)
I've found out that when you use (A) on var two, the regexp returns an empty string ''; while when you use (B) the regexp returns null.
You have to be careful with that.
Does anyone knows if this is a cross-browser behavior?
I've tested this on Google Chrome (Webkit) build 15.
UPDATE: Whoa, just did some tests on Internet Explorer 8, and it returns an empty string '' for both cases. So my conclusion is that the best alternative is to use (A) and then test for an empty string.
Technically (A) should return '' on HELLOBYE because the capturing brackets can capture both an 'x' and an empty string, since the ? is inside the capturing group.
Whereas in (B), the capturing brackets can only ever capture the string x. If the x is not present, then the group is never captured at all, because the entire group is optional, as opposed to the regex within the group.
Subtle difference!
So a browser or regex engine will always return '' for (A), but what it returns for (B) isn't all that well defined, so may differ depending on implementation - Chrome distinguishes between "the group matched an empty string" and "the group didn't match at all". Whereas IE doesn't make this distinction (or if it does, it coerces the return type for the second case into an empty string).
Summary -- use (A) because you know that if there is no x then the capturing group definitely matches ''. Using (B) depends on whether a browser distinguishes between "zero-length match" and "no match at all".
I am trying to match a string containing a mix of digits and hyphenated digits, like a crossword answer specification, for example 1,2-2 or 1-1,3,4,2-2
/,?(([1-9]-[1-9])|([1-9]))/g is what I've come up to match the string
value = value.replace(/,?(([1-9]-[1-9])|([1-9]))/g, '');
replaces ok, and I've checked it out in an online tester.
What I really need is to negate this, so I can use it on a keyup event, examine the contents of a textarea and remove characters that don't fit, so it only allows through characters as in the example.
I've tried ^ where expected, but this it's not doing what I expect, how should I negate the regex so I remove everything that doesn't match?
If there is a better way of doing this I'm open to suggestions too.
var value = 'hello,1,2,3,4-6,1-1,3,test,4,2-2';
var pattern = /,?(([1-9]-[1-9])|([1-9]))/g;
value.replace(pattern, ''); // "hello,test"
You can use String#match. With /g flag, it returns an array of all the matches, then you can use Array#join to join them.
The problem is that String#match returns null when there is no match, so you have to handle that case and use an empty array so that it can join:
(value.match(pattern) || []).join(''); // ",1,2,3,4-6,1-1,3,4,2-2"
Note: It may better to check them on onblur rather than onkeyup. Messing with the text that the user is currently typing will make it annoying. Better to wait for the user to finish typing.
Didn't test it in JS, but this should return the valid string beginning from the left and as long as valid values are encountered (note that I used \d - if you'd like 1-9 only, then use your brackets).
(?:\d(?:-\d)?,)*\d(?:-\d)?
E.g. matching this regular expression with the string "0-1,1,2,3,4-4,2,,1,3--4" will return "0-1,1,2,3,4-4,2" as the first match.
I am using the following Javascript to read strings out of a text file and process them with a regular expression
while (!textFile.AtEndOfStream)
{
currLine = textFile.ReadLine();
match = re.exec(currLine);
do stuff with match
}
The problem I have is that every other time re.exec is called it fails and returns null; so the first row is processed correctly, but the second row results in null, then the third row works, and the fourth row results in null.
I can use the following code to get the result I want
while (!textFile.AtEndOfStream)
{
currLine = textFile.ReadLine();
match = re.exec(currLine);
if (match == null) match = re.exec(currLine);
}
but that seems a bit of a nasty kludge. Can anyone tell my why this happens and what I can do to fix it properly?
Your re is defined with the ‘global’ modifier, eg. something like /foo/g.
When a RegExp is global, it retains hidden state in the RegExp instance itself to remember the last place it matched. The next time you search, it'll search forward from the index of the end of the last match, and find the next match from there. If you're passing a different string to the one you passed last time, this will give highly unpredictable results!
When you use global regexps, you should exhaust them by calling them repeatedly until you get null. Then the next time you use it you'll be matching from the start of the string again. Alternatively you can explicitly set re.lastIndex to 0 before using one. If you only want to test for the existence of one match, as in this example, simplest is just not to use g.
The JS RegExp interfaces is one of the most confusing, poorly-designed parts of the language. (And this is JavaScript, so that's saying a lot.)
Javascript regular expressions keep some state between executions and you are probably falling in to that trap.
I always use the String.match function and have never been bitten :
while (!textFile.AtEndOfStream)
{
match = textFile.ReadLine ().match (re);
do stuff with match
}