Related
I am trying to write password validation function with regexp and don't know how to do it.
The regex package provided by the standard API of the Go language is different to other languages.
Have someone an idea, how this regexp pattern should looks like?
The pattern should validate:
/*
* Password rules:
* at least 7 letters
* at least 1 number
* at least 1 upper case
* at least 1 special character
*/
That's actually impossible since Go's regex doesn't support backtracking.
However, it's easy to implement, a simple example:
func verifyPassword(s string) (sevenOrMore, number, upper, special bool) {
letters := 0
for _, c := range s {
switch {
case unicode.IsNumber(c):
number = true
case unicode.IsUpper(c):
upper = true
letters++
case unicode.IsPunct(c) || unicode.IsSymbol(c):
special = true
case unicode.IsLetter(c) || c == ' ':
letters++
default:
//return false, false, false, false
}
}
sevenOrMore = letters >= 7
return
}
The right regexp would be... no regexp here.
You can define a custom function that would validate the password, and combine it with other frameworks helping validating a field, like mccoyst/validate (mentioned in this discussion about parameter validation)
You also have go-validator/validator whic allows to define similar validations (but I would still use a custom validator instead of one or several regexps).
Note: go regexp is based on re2, an efficient, principled regular expression library).
So the major trade offs are no back-references for example: (abc)\1 and no matching look-behinds.
In exchange you get high speed regex.
Building from a neighboring answer, I too wrote a helper function that works well for me. This one just assumes overall password length is satisfactory. Check out the following...
func isValid(s string) bool {
var (
hasMinLen = false
hasUpper = false
hasLower = false
hasNumber = false
hasSpecial = false
)
if len(s) >= 7 {
hasMinLen = true
}
for _, char := range s {
switch {
case unicode.IsUpper(char):
hasUpper = true
case unicode.IsLower(char):
hasLower = true
case unicode.IsNumber(char):
hasNumber = true
case unicode.IsPunct(char) || unicode.IsSymbol(char):
hasSpecial = true
}
}
return hasMinLen && hasUpper && hasLower && hasNumber && hasSpecial
}
isValid("pass") // false
isValid("password") // false
isValid("Password") // false
isValid("P#ssword") // false
isValid("P#ssw0rd") // true
Go Playground example
Based on #OneOfOne's answer with some error message improvement
package main
import (
"fmt"
"strings"
"unicode"
)
func verifyPassword(password string) error {
var uppercasePresent bool
var lowercasePresent bool
var numberPresent bool
var specialCharPresent bool
const minPassLength = 8
const maxPassLength = 64
var passLen int
var errorString string
for _, ch := range password {
switch {
case unicode.IsNumber(ch):
numberPresent = true
passLen++
case unicode.IsUpper(ch):
uppercasePresent = true
passLen++
case unicode.IsLower(ch):
lowercasePresent = true
passLen++
case unicode.IsPunct(ch) || unicode.IsSymbol(ch):
specialCharPresent = true
passLen++
case ch == ' ':
passLen++
}
}
appendError := func(err string) {
if len(strings.TrimSpace(errorString)) != 0 {
errorString += ", " + err
} else {
errorString = err
}
}
if !lowercasePresent {
appendError("lowercase letter missing")
}
if !uppercasePresent {
appendError("uppercase letter missing")
}
if !numberPresent {
appendError("atleast one numeric character required")
}
if !specialCharPresent {
appendError("special character missing")
}
if !(minPassLength <= passLen && passLen <= maxPassLength) {
appendError(fmt.Sprintf("password length must be between %d to %d characters long", minPassLength, maxPassLength))
}
if len(errorString) != 0 {
return fmt.Errorf(errorString)
}
return nil
}
// Let's test it
func main() {
password := "Apple"
err := verifyPassword(password)
fmt.Println(password, " ", err)
}
Below it's my implementation of the above answers with custom messages and somehow twisting to them in a good way(performance aware codes).
package main
import (
"fmt"
"strconv"
"unicode"
)
func main() {
pass := "12345678_Windrol"
// call the password validator and give it field name to be known by the user, password, and the min and max password length
isValid, errs := isValidPassword("Password", pass, 8, 32)
if isValid {
fmt.Println("The password is valid")
} else {
for _, v := range errs {
fmt.Println(v)
}
}
}
func isValidPassword(field, s string, min, max int) (isValid bool, errs []string) {
var (
isMin bool
special bool
number bool
upper bool
lower bool
)
//test for the muximum and minimum characters required for the password string
if len(s) < min || len(s) > max {
isMin = false
appendError("length should be " + strconv.Itoa(min) + " to " + strconv.Itoa(max))
}
for _, c := range s {
// Optimize perf if all become true before reaching the end
if special && number && upper && lower && isMin {
break
}
// else go on switching
switch {
case unicode.IsUpper(c):
upper = true
case unicode.IsLower(c):
lower = true
case unicode.IsNumber(c):
number = true
case unicode.IsPunct(c) || unicode.IsSymbol(c):
special = true
}
}
// append error
appendError := func(err string) {
errs = append(errs, field+" "+err)
}
// Add custom error messages
if !special {
appendError("should contain at least a single special character")
}
if !number {
appendError("should contain at least a single digit")
}
if !lower {
appendError("should contain at least a single lowercase letter")
}
if !upper {
appendError("should contain at least single uppercase letter")
}
// if there is any error
if len(errs) > 0 {
return false, errs
}
// everyting is right
return true, errs
}
There are many ways to skin a cat---The other answers seem to veer away from regex completely, so I thought I'd show my method for simple pass/fail testing of a password string, which is styled to suit my thinking. (Note that this doesn't meet the literal "7 letters" requirement in the original question, but does check overall length.) To me, this code is fairly simple and looks easier to read than doing switch statements or a bunch of if statements:
password := "Pa$$w0rd"
secure := true
tests := []string{".{7,}", "[a-z]", "[A-Z]", "[0-9]", "[^\\d\\w]"}
for _, test := range tests {
t, _ := regexp.MatchString(test, password)
if !t {
secure = false
break
}
}
//secure will be true, since the string "Pa$$w0rd" passes all the tests
I am new to regex, can you please tell me how to take a query parameter with all the below combinations.
(ParamName=Operator:ParamValue) is my set of query parameter value. This will be separated with ;(AND) or ,(OR) and i want to group them within braces. Like in below example
Ex: http://,host:port>/get?search=(date=gt:2020-02-06T00:00:00.000Z;(name=eq:Test,department=co:Prod))
Here the date should be greater than 2020-02-06 and name = Test or department contains Prod.
How to parse these query parameters. Please suggest.
Thanks, Vijay
So, I wrote a solution in JavaScript, but it should be adaptable in other languages as well, with a bit of research.
It's quite a bit of code, but what you're looking to achieve is not super easy!
So here's the code bellow, it's thoroughly commented, but please, if you there is something you don't understand, ask away, and I'll be happy to answer you :)
//
// The 2 first regexes are a parameter, which looks like date=gt:2020-02-06T00:00:00.000Z for example.
// The difference between those 2 is that the 1st one has **named capture group**
// For example '(?<operator>...)' is a capture group named 'operator'.
// This will come in handy in the code, to keep things clean
//
const RX_NAMED_PARAMETER = /(?:(?<param>\w+)=(?<operator>\w+):(?<value>[\w-:.]+))/
const parameter = "((\\w+)=(\\w+):([\\w-:.]+)|(true|false))"
//
// The 3rd parameter is an operation between 2 parameters
//
const RX_OPERATION = new RegExp(`\\((?<param1>${parameter})(?:(?<and_or>[,;])(?<param2>${parameter}))?\\)`, '');
// '---------.---------' '-------.------' '----------.---------'
// 1st parameter AND or OR 2nd parameter
my_data = {
date: new Date(2000, 01, 01),
name: 'Joey',
department: 'Production'
}
/**
* This function compates the 2 elements, and returns the bigger one.
* The elements might be dates, numbers, or anything that can be compared.
* The elements **need** to be of the same type
*/
function isGreaterThan(elem1, elem2) {
if (elem1 instanceof Date) {
const date = new Date(elem2).getTime();
if (isNaN(date))
throw new Error(`${elem2} - Not a valid date`);
return elem1.getTime() > date;
}
if (typeof elem1 === 'number') {
const num = Number(elem2);
if (isNaN(num))
throw new Error(`${elem2} - Not a number`);
return elem1 > num;
}
return elem1 > elem2;
}
/**
* Makes an operation as you defined them in your
* post, you might want to change that to suit your needs
*/
function operate(param, operator, value) {
if (!(param in my_data))
throw new Error(`${param} - Invalid parameter!`);
switch (operator) {
case 'eq':
return my_data[param] == value;
case 'co':
return my_data[param].includes(value);
case 'lt':
return isGreaterThan(my_data[param], value);
case 'gt':
return !isGreaterThan(my_data[param], value);
default:
throw new Error(`${operator} - Unsupported operation`);
}
}
/**
* This parses the URL, and returns a boolean
*/
function parseUri(uri) {
let finalResult;
// As long as there are operations (of the form <param1><; or ,><param2>) on the URL
while (RX_OPERATION.test(uri)) {
// We replace the 1st operation by the result of this operation ("true" or "false")
uri = uri.replace(RX_OPERATION, rawOperation => {
// As long as there are parameters in the operations (e.g. "name=eq:Bob")
while (RX_NAMED_PARAMETER.test(rawOperation)) {
// We replace the 1st parameter by its value ("true" or "false")
rawOperation = rawOperation.replace(RX_NAMED_PARAMETER, rawParameter => {
const res = RX_NAMED_PARAMETER.exec(rawParameter);
return '' + operate(
res.groups.param,
res.groups.operator,
res.groups.value,
);
// The "res.groups.xxx" syntax is allowed by the
// usage of capture groups. See the top of the file.
});
}
// At this point, the rawOperation should look like
// (true,false) or (false;false) for example
const res = RX_OPERATION.exec(rawOperation);
let operation;
if (res.groups.param2 === undefined)
operation = res.groups.param1; // In case this is an isolated operation
else
operation = res.groups.param1 + ({',': ' || ', ';': ' && '}[res.groups.and_or]) + res.groups.param2;
finalResult = eval(operation);
return '' + finalResult;
});
}
return finalResult;
}
let res;
res = parseUri("http://,host:port>/get?search=(date=gt:2020-02-06T00:00:00.000Z;(name=eq:Test,department=co:Prod))");
console.log(res);
res = parseUri("http://,host:port>/get?search=(date=lt:2020-02-06T00:00:00.000Z)");
console.log(res);
At the moment I'm trying to use a regular expression to find usernames. The following condition is what I need:
"Username matches the search term with a maximum of 3 wrong characters"
For example,
Database content:
"MyUsername"
Search command -> returning match:
search("Username") -> "MyUsername"
search("Us3rname") -> "MyUsername"
search("userName") -> "MyUsername"
search("MyUser") -> none (4 characters wrong)
search("My Us3r N#me") -> none (4 characters wrong)
I can build my regex dynamically and push this to a database query. I only can't get a grip on the regex itself. Could you help me with this? Would be great? (or is it even possible?)
You can't do this with regular expression. You need some similarity algorithm to check the similarity between two strings.
A good start and an easy one is the levensthein distance.
In short: It calculates how many Insert/Update/Delete Operations are needed to transform string A to string B.
I had done this in Javascript some years ago, but it should be easy in nearly every programming language. You can find a working example here:
// http://ejohn.org/blog/fast-javascript-maxmin/
Array.max = function( array ){
return Math.max.apply( Math, array );
};
Array.min = function( array ){
return Math.min.apply( Math, array );
};
// Levenshstein Distance Calculation
function levenshtein_distance (t1, t2) {
var countI = t1.length+1;
var countJ = t2.length+1;
// build empty 'matrix'
var matrix = new Array (countI);
for (var i=0;i<countI;i++) {
matrix[i] = new Array (countJ);
}
// initialize the matrix;
// set m(0,0) = 0;
// m(0,0<=j<countJ) = j
// m(0<=i<countI, 0) = i
matrix[0][0] = 0;
for (var j=1;j<matrix[0].length;j++) {
matrix[0][j] = j;
}
for (var i=1;i<matrix.length;i++) {
matrix[i][0] = i;
}
// calculate the matrix
for (var i=1;i<matrix.length;i++) {
for (var j=1;j<matrix[i].length;j++) {
var costs = new Array ();
if (t1.charAt(i-1) == t2.charAt(j-1)) {
costs.push (matrix[i-1][j-1]);
}
costs.push (matrix[i-1][j-1] + 1);
costs.push (matrix[i][j-1] + 1);
costs.push (matrix[i-1][j] + 1);
matrix[i][j] = Array.min(costs);
}
}
// resultMatrix = matrix;
var result = new Object
result.distance = matrix[countI-1][countJ-1];
result.matrix = matrix;
return result;
}
I need to define a bunch of vector sequences, which are all a series of L,D,R,U for left, down, right, up or x for break. There are optional parts, and either/or parts. I have been using my own invented system for noting it down, but I want to document this for other, potentially non-programmers to read.
I now want to use a subset (I don't plan on using any wildcards, or infinite repetition for example) of regex to define the vector sequence and a script to produce all possible matching strings...
/LDR/ produces ['LDR']
/LDU?R/ produces ['LDR','LDUR']
/R(LD|DR)U/ produces ['RLDU','RDRU']
/DxR[DL]U?RDRU?/ produces ['DxRDRDR','DxRDRDRU','DxRDURDR','DxRDURDRU','DxRLRDR','DxRLRDRU','DxRLURDR','DxRLURDRU']
Is there an existing library I can use to generate all matches?
EDIT
I realised I will only be needing or statements, as optional things can be specified by thing or nothing maybe a, or b, both optional could be (a|b|). Is there another language I could use to define what I am trying to do?
By translating the java code form the link provided by #Dukeling into javascript, I think I have solved my problem...
var Node = function(str){
this.bracket = false;
this.children = [];
this.s = str;
this.next = null;
this.addChild = function(child){
this.children.push(child);
}
}
var printTree = function(root,prefix){
prefix = prefix.replace(/\./g, "");
for(i in root.children){
var child = root.children[i]
printTree(child, prefix + root.s);
}
if(root.children.length < 1){
console.log(prefix + root.s);
}
}
var Stack = function(){
this.arr = []
this.push = function(item){
this.arr.push(item)
}
this.pop = function(){
return this.arr.pop()
}
this.peek = function(){
return this.arr[this.arr.length-1]
}
}
var createTree = function(s){
// this line was causing errors for `a(((b|c)d)e)f` because the `(((` was only
// replacing the forst two brackets.
// var s = s.replace(/(\(|\||\))(\(|\||\))/g, "$1.$2");
// this line fixes it
var s = s.replace(/[(|)]+/g, function(x){ return x.split('').join('.') });
var str = s.split('');
var stack = new Stack();
var root = new Node("");
stack.push(root); // start node
var justFinishedBrackets = false;
for(i in str){
var c = str[i]
if(c == '('){
stack.peek().next = new Node("Y"); // node after brackets
stack.peek().bracket = true; // node before brackets
} else if (c == '|' || c == ')'){
var last = stack.peek(); // for (ab|cd)e, remember b / d so we can add child e to it
while (!stack.peek().bracket){ // while not node before brackets
stack.pop();
}
last.addChild(stack.peek().next); // for (b|c)d, add d as child to b / c
} else {
if (justFinishedBrackets){
var next = stack.pop().next;
next.s = "" + c;
stack.push(next);
} else {
var n = new Node(""+c);
stack.peek().addChild(n);
stack.push(n);
}
}
justFinishedBrackets = (c == ')');
}
return root;
}
// Test it out
var str = "a(c|mo(r|l))e";
var root = createTree(str);
printTree(root, "");
// Prints: ace / amore / amole
I only changed one line, to allow more than two consecutive brackets to be handled, and left the original translation in the comments
I also added a function to return an array of results, instead of printing them...
var getTree = function(root,prefix){
this.out = this.out || []
prefix = prefix.replace(/\./g, "");
for(i in root.children){
var child = root.children[i]
getTree(child, prefix + root.s, out);
}
if(root.children.length < 1){
this.out.push(prefix + root.s);
}
if(!prefix && !root.s){
var out = this.out;
this.out = null
return out;
}
}
// Test it
var str = "a(b|c)d";
var root = createTree(str);
console.log(getTree(root, ""));
// logs ["abd","acd"]
The last part, to allow for empty strings too, so... (ab|c|) means ab or c or nothing, and a convenience shortcut so that ab?c is translated into a(b|)c.
var getMatches = function(str){
str = str.replace(/(.)\?/g,"($1|)")
// replace all instances of `(???|)` with `(???|µ)`
// the µ will be stripped out later
str = str.replace(/\|\)/g,"|µ)")
// fix issues where last character is `)` by inserting token `µ`
// which will be stripped out later
str = str+"µ"
var root = createTree(str);
var res = getTree(root, "");
// strip out token µ
for(i in res){
res[i] = res[i].replace(/µ/g,"")
}
// return the array of results
return res
}
getMatches("a(bc|de?)?f");
// Returns: ["abcf","adef","adf","af"]
The last part is a little hack-ish as it relies on µ not being in the string (not an issue for me) and solves one bug, where a ) at the end on the input string was causing incorrect output, by inserting a µ at the end of each string, and then stripping it from the results. I would be happy for someone to suggest a better way to handle these issues, so it can work as a more general solution.
This code as it stands does everything I need. Thanks for all your help!
I'd imagine what you're trying is quite easy with a tree (as long as it's only or-statements).
Parse a(b|c)d (or any or-statement) into a tree as follows: a has children b and c, b and c have a mutual child d. b and c can both consist of 0 or more nodes (as in c could be g(e|f)h in which case (part of) the tree would be a -> g -> e/f (2 nodes) -> h -> d or c could be empty, in which case (part of) the tree would be a -> d, but an actual physical empty node may simplify things, which you should see when trying to write the code).
Generation of the tree shouldn't be too difficult with either recursion or a stack.
Once you have a tree, it's trivial to recursively iterate through the whole thing and generate all strings.
Also, here is a link to a similar question, providing a library or two.
EDIT:
"shouldn't be too difficult" - okay, maybe not
Here is a somewhat complicated example (Java) that may require some advanced knowledge about stacks.
Here is a slightly simpler version (Java) thanks to inserting a special character between each ((, )), |(, etc.
Note that neither of these are particularly efficient, the point is just to get the idea across.
Here is a JavaScript example that addresses parsing the (a|b) and (a|b|) possibilities, creates an array of possible substrings, and composes the matches based on this answer.
var regex = /\([RLUD]*\|[RLUD]*\|?\)/,
str = "R(LD|DR)U(R|L|)",
substrings = [], matches = [], str_tmp = str, find
while (find = regex.exec(str_tmp)){
var index = find.index
finds = find[0].split(/\|/)
substrings.push(str_tmp.substr(0, index))
if (find[0].match(/\|/g).length == 1)
substrings.push([finds[0].substr(1), finds[1].replace(/.$/, '')])
else if (find[0].match(/\|/g).length == 2){
substrings.push([finds[0].substr(1), ""])
substrings.push([finds[1], ""])
}
str_tmp = str_tmp.substr(index + find[0].length)
}
if (str_tmp) substrings.push([str_tmp])
console.log(substrings) //>>["R", ["LD", "DR"], "U", ["R", ""], ["L", ""]]
//compose matches
function printBin(tree, soFar, iterations) {
if (iterations == tree.length) matches.push(soFar)
else if (tree[iterations].length == 2){
printBin(tree, soFar + tree[iterations][0], iterations + 1)
printBin(tree, soFar + tree[iterations][1], iterations + 1)
}
else printBin(tree, soFar + tree[iterations], iterations + 1)
}
printBin(substrings, "", 0)
console.log(matches) //>>["RLDURL", "RLDUR", "RLDUL", "RLDU", "RDRURL", "RDRUR", "RDRUL", "RDRU"]
I am trying to extend dijit.form.FilteringSelect with the requirement that all instances of it should match input regardless of where the characters are in the inputted text, and should also ignore whitespace and punctuation (mainly periods and dashes).
For example if an option is "J.P. Morgan" I would want to be able to select that option after typing "JP" or "P Morgan".
Now I know that the part about matching anywhere in the string can be accomplished by passing in queryExpr: "*${0}*" when creating the instance.
What I haven't figured out is how to make it ignore whitespace, periods, and dashes. I have an example of where I'm at here - http://jsfiddle.net/mNYw2/2/. Any help would be appreciated.
the thing to master in this case is the store fetch querystrings.. It will call a function in the attached store to pull out any matching items, so if you have a value entered in the autofilling inputfield, it will eventually end up similar to this in the code:
var query = { this.searchAttr: this.get("value") }; // this is not entirely accurate
this._fetchHandle = this.store.query(query, options);
this._fetchHandle.then( showResultsFunction );
So, when you define select, override the _setStoreAttr to make changes in the store query api
dojo.declare('CustomFilteringSelect', [FilteringSelect], {
constructor: function() {
//???
},
_setStoreAttr: function(store) {
this.inherited(arguments); // allow for comboboxmixin to modify it
// above line eventually calls this._set("store", store);
// so now, 'this' has 'store' set allready
// override here
this.store.query = function(query, options) {
// note that some (Memory) stores has no 'fetch' wrapper
};
}
});
EDIT: override queryEngine function as opposed to query function
Take a look at the file SimpleQueryEngine.js under dojo/store/util. This is essentially what filters the received Array items on the given String query from the FilteringSelect. Ok, it goes like this:
var MyEngine = function(query, options) {
// create our matching query function
switch(typeof query){
default:
throw new Error("Can not query with a " + typeof query);
case "object": case "undefined":
var queryObject = query;
query = function(object){
for(var key in queryObject){
var required = queryObject[key];
if(required && required.test){
if(!required.test(object[key])){
return false;
}
}else if(required != object[key]){
return false;
}
}
return true;
};
break;
case "string":
/// HERE is most likely where you can play with the reqexp matcher.
// named query
if(!this[query]){
throw new Error("No filter function " + query + " was found in store");
}
query = this[query];
// fall through
case "function":
// fall through
}
function execute(array){
// execute the whole query, first we filter
var results = arrayUtil.filter(array, query);
// next we sort
if(options && options.sort){
results.sort(function(a, b){
for(var sort, i=0; sort = options.sort[i]; i++){
var aValue = a[sort.attribute];
var bValue = b[sort.attribute];
if (aValue != bValue) {
return !!sort.descending == aValue > bValue ? -1 : 1;
}
}
return 0;
});
}
// now we paginate
if(options && (options.start || options.count)){
var total = results.length;
results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
results.total = total;
}
return results;
}
execute.matches = query;
return execute;
};
new Store( { queryEngine: MyEngine });
when execute.matches is set on bottom of this function, what happens is, that the string gets called on each item. Each item has a property - Select.searchAttr - which is tested by RegExp like so: new RegExp(query).test(item[searchAttr]); or maybe a bit simpler to understand; item[searchAttr].matches(query);
I have no testing environment, but locate the inline comment above and start using console.debug..
Example:
Stpre.data = [
{ id:'WS', name: 'Will F. Smith' },
{ id:'RD', name:'Robert O. Dinero' },
{ id:'CP', name:'Cle O. Patra' }
];
Select.searchAttr = "name";
Select.value = "Robert Din"; // keyup->autocomplete->query
Select.query will become Select.queryExp.replace("${0]", Select.value), in your simple queryExp case, 'Robert Din'.. This will get fuzzy and it would be up to you to fill in the regular expression, here's something to start with
query = query.substr(1,query.length-2); // '*' be gone
var words = query.split(" ");
var exp = "";
dojo.forEach(words, function(word, idx) {
// check if last word
var nextWord = words[idx+1] ? words[idx+1] : null;
// postfix 'match-all-but-first-letter-of-nextWord'
exp += word + (nextWord ? "[^" + nextWord[0] + "]*" : "");
});
// exp should now be "Robert[^D]*Din";
// put back '*'
query = '*' + exp + '*';