JS: Check string if it is failing for some rules - javascript

Issue
Using regex to verify if a string is matching specific rules.
My Problem
My regexes seems not to bee valid and I don't know how to check a string for multiple regexes.
Example string
This is just a senseless string with less then 1.000,00 words. and 1 x abbrevations e.g. this one ( and so on).
Rules
Every sentence must begin with an upper case character or a number
There must not be a space between number and `x`
Never multiple spaces
There must not be spaces at the beginning and at the end of bracket content
My regex attempts
/([.?!])\s*(?= [A-Z0-9])/g // Sentence have to start with upper case
/([0-9]*)(x)/g // No space between number and 'x'
/\s{2,}/g // Two or more spaces
// don't know how to do last rule
if (/([.?!])\s*(?= [A-Z0-9])/.test(string); )
failing.push('capitalizeSentence');
else if ...
But maybe it can by done a bit more dynamic...
Expected result
I need to know which rules are not matching the string if there is any. So I would suggest an array with values for those rules failed.
So in this example string the result could be an array like this, as every rule is failing.
failing = [ 'capitalizeSentence', 'spaceNumber', 'multipleSpaces', 'spaceBrackets' ];

Something like this:
var rules = {
'capitalizeSentence': /[.?!]\s+[^A-Z\d]/,
'spaceNumber': /\d\s+x/,
'multipleSpaces': /\s\s/,
'spaceBrackets': /\(\s|\s\)/
}
var check = function(str){
return Object.keys(rules).reduce(function(results,key){
if(rules[key].test(str)) {
results.push(key);
}
return results;
},[]);
};
console.log(check('This is just a senseless string with less then 1.000,00 words. and 1 x abbrevations e.g. this one ( and so on).'));
Operates by checking for rules violations and adding those violation names to an array which is returned.

Related

Regex- match 3 or 6 of type

I'm writing an application that requires color manipulation, and I want to know when the user has entered a valid hex value. This includes both '#ffffff' and '#fff', but not the ones in between, like 4 or 5 Fs. My question is, can I write a regex that determines if a character is present a set amount of times or another exact amount of times?
What I tried was mutating the:
/#(\d|\w){3}{6}/
Regular expression to this:
/#(\d|\w){3|6}/
Obviously this didn't work. I realize I could write:
/(#(\d|\w){3})|(#(\d|\w){6})/
However I'm hoping for something that looks better.
The shortest I could come up with:
/#([\da-f]{3}){1,2}/i
I.e. # followed by one or two groups of three hexadecimal digits.
You can use this regex:
/#[a-f\d]{3}(?:[a-f\d]{3})?\b/i
This will allow #<3 hex-digits> or #<6 hex-digits> inputs. \b in the end is for word boundary.
RegEx Demo
I had to find a pattern for this myself today but I also needed to include the extra flag for transparency (i.e. #FFF5 / #FFFFFF55). Which made things a little more complicated as the valid combinations goes up a little.
In case it's of any use, here's what I came up with:
var inputs = [
"#12", // Invalid
"#123", // Valid
"#1234", // Valid
"#12345", // Invalid
"#123456", // Valid
"#1234567", // Invalid
"#12345678", // Valid
"#123456789" // Invalid
];
var regex = /(^\#(([\da-f]){3}){1,2}$)|(^\#(([\da-f]){4}){1,2}$)/i;
inputs.forEach((itm, ind, arr) => console.log(itm, (regex.test(itm) ? "valid" : "-")));
Which should return:
#123 valid
#1234 valid
#12345 -
#123456 valid
#1234567 -
#12345678 valid
#123456789 -

Javascript Regex doesn't match with my String

I have the following String :
var resultLine= "[UT] - GSM incoming call : STEP 1 - Simulate reception from server (1)Rerun3713 msAssertion ok"
And the following code which is responsible to check of the String matched with the Regex :
var resultRE = /^([ \w-]*: )?(.+) \((\d+), (\d+), (\d+)\)Rerun/;
var resultMatch = resultLine.match(resultRE);
if (resultMatch) {
return true;
} else {
return false;
}
In this case, i have an error in my Regex because i always get "false".
Where is my mistake ?
I would recommend the following pattern based on what it appears you are looking for:
var resultRE = /^([\[ \w\]-]*: )(.+) \(([0-9, ]*)\)Rerun(.*)$/
This should force all capture groups to exist, even if they are empty, and will allow for multiple numbers before Rerun as you seem to expect.
This matches nothing in your string
([ \w-]*: )?
Since it was optional, that doesn't matter because it gets caught by the all inclusive
(.+)
If you were trying to match the [UT] part with it's separator, it would look something like this
(\[\w+\][\s\-]*)?
As noted in the comments, you only have one number in parentheses but your regex requires three sets of them, separated by commas. This will allow any number of numbers, separated by commas indefinitely (I don't know if there's a limit or not).
\((\d+,\s)*(\d+)\)
If you need something more specific, you'll have to be more specific about what template your matching, not a specific case. But the best I can figure with what you've provided is
^(\[\w\][\s\-]*)?(.+)\((\d+,\w)*(\d+)\)Rerun
var resultRE = /\((\d+)(?:, (\d+))?(?:, (\d+))?\)Rerun/;
if (resultRE.test(resultLine)) {
var num1 = RegExp.$1,
num2 = RegExp.$2,
num3 = RegExp.$3;
}

Matching special characters and letters in regex

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

Regular Expression with multiple words (in any order) without repeat

I'm trying to execute a search of sorts (using JavaScript) on a list of strings. Each string in the list has multiple words.
A search query may also include multiple words, but the ordering of the words should not matter.
For example, on the string "This is a random string", the query "trin and is" should match. However, these terms cannot overlap. For example, "random random" as a query on the same string should not match.
I'm going to be sorting the results based on relevance, but I should have no problem doing that myself, I just can't figure out how to build up the regular expression(s). Any ideas?
The query trin and is becomes the following regular expression:
/trin.*(?:and.*is|is.*and)|and.*(?:trin.*is|is.*trin)|is.*(?:trin.*and|and.*trin)/
In other words, don't use regular expressions for this.
It probably isn't a good idea to do this with just a regular expression. A (pure, computer science) regular expression "can't count". The only "memory" it has at any point is the state of the DFA. To match multiple words in any order without repeat you'd need on the order of 2^n states. So probably a really horrible regex.
(Aside: I mention "pure, computer science" regular expressions because most implementations are actually an extension, and let you do things that are non-regular. I'm not aware of any extensions, certainly none in JavaScript, that make doing what you want to do any less painless with a single pattern.)
A better approach would be to keep a dictionary (Object, in JavaScript) that maps from words to counts. Initialize it to your set of words with the appropriate counts for each. You can use a regular expression to match words, and then for each word you find, decrement the corresponding entry in the dictionary. If the dictionary contains any non-0 values at the end, or if somewhere a long the way you try to over-decrement a value (or decrement one that doesn't exist), then you have a failed match.
I'm totally not sure if I get you right there, so I'll just post my suggestion for it.
var query = "trin and is",
target = "This is a random string",
search = { },
matches = 0;
query.split( /\s+/ ).forEach(function( word ) {
search[ word ] = true;
});
Object.keys( search ).forEach(function( word ) {
matches += +new RegExp( word ).test( target );
});
// do something useful with "matches" for the query, should be "3"
alert( matches );
So, the variable matches will contain the number of unique matches for the query. The first split-loop just makes sure that no "doubles" are counted since we would overwrite our search object. The second loop checks for the individuals words within the target string and uses the nifty + to cast the result (either true or false) into a number, hence, +1 on a match or +0.
I was looking for a solution to this issue and none of the solutions presented here was good enough, so this is what I came up with:
function filterMatch(itemStr, keyword){
var words = keyword.split(' '), i = 0, w, reg;
for(; w = words[i++] ;){
reg = new RegExp(w, 'ig');
if (reg.test(itemStr) === false) return false; // word not found
itemStr = itemStr.replace(reg, ''); // remove matched word from original string
}
return true;
}
// test
filterMatch('This is a random string', 'trin and is'); // true
filterMatch('This is a random string', 'trin not is'); // false

Regular Expression to match given word in last five words of pipe-delimited string

Say we have a string
blue|blue|green|blue|blue|yellow|yellow|blue|yellow|yellow|
And we want to figure out whether the word "yellow" occurs in the last 5 words of the string, specifically by returning a capture group containing these occurences if any.
Is there a way to do that with a regex?
Update: I'm feeding a regex engine some rules. For various reasons I'm trying to work with the engine rather than go outside it, which would be my last resort.
/\b(yellow)\|(?=(?:\w+\|){0,4}$)/g
This will return one hit for each yellow| that's followed by fewer than five words (per your definition of "word"). This assumes the sequence always ends with a pipe; if that's not the case, you might want to change it to:
/\b(yellow)(?=(?:\|\w+){0,4}\|?$)/g
EDIT (in response to comment): The definition of a "word" in this solution is arbitrary, and doesn't really correspond to real-world usage. To allow for hyphenated words like "real-world" you could use this:
/\b(yellow)\|(?=(?:\w+(?:-\w+)*\|){0,4}$)/g
...or, for this particular job, you could define a word as one or more of any characters except pipes:
/\b(yellow)\|(?=(?:[^|]+\|){0,4}$)/g
No need to use a Regex for such a simple thing.
Simply split on the pipe, and check with indexOf:
var group = 'blue|blue|green|blue|blue|yellow|yellow|blue|yellow|yellow';
if ( group.split('|').slice(-5).indexOf('yellow') == -1 ) {
alert('Not there :(');
} else {
alert('Found!!!');
}
Note: indexOf is not natively supported in IE < 9, but support for it can be added very easily.
Can't think of a way to do this with a single regular expression, but you can form one for each of the last five positions and sum the matches.
var string = "blue|blue|green|blue|blue|yellow|yellow|blue|yellow|yellow|";
var regexes = [];
regexes.push(/(yellow)\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|$/);
regexes.push(/(yellow)\|[^|]+\|[^|]+\|[^|]+\|$/);
regexes.push(/(yellow)\|[^|]+\|[^|]+\|$/);
regexes.push(/(yellow)\|[^|]+\|$/);
regexes.push(/(yellow)\|$/);
var count = 0;
var regex;
while (regex = regexes.shift()) {
if (string.match(regex)) {
count++;
}
}
console.log(count);
Should find four matches.

Categories