Regex Javascript, negative lookahead with white space - javascript

In my Javascript angular application I have a regex to validate usernames.
The issue I am facing, after doing much research is that utilising negative lookahead with expressions that contain white spaces is not working.
The Requirements
Username can be composed of many alphanumeric strings split at most with one space. Spaces at edges are not allowed. also the username should be filtered against a couple of banned names.
1)
(/^[a-zA-Z\d]+([\s][a-zA-Z\d]+)+?$/).test("admin may not be used")
allows alphanumeric words to be split by one consequent space at a time, and disallows spaces at edges
2)
(/^(?!(?:admin|alfred)$)[a-zA-Z\d]+$/).test("admin")
works and word admin is not allowed
3) merging both:
(/^(?!(?:admin|alfred)$)[a-zA-Z\d]+([\s][a-zA-Z\d]+)+?$/).test("admin may not be used")
fails! and will allow the banned word admin to be used.
Expected Result:
Both filters are expected to work, that is the banned words list , as well as consequent space filter.
Can you please point what possibly is wrong with my expression?

You may consider using
/^(?!.*\b(?:admin|alfred)\b)[a-zA-Z\d]+(?:\s[a-zA-Z\d]+)+$/
or a bit longer one that is a bit more effecient (but less readable):
/^(?!(?:admin|alfred)\b)[a-zA-Z\d]+(?:\s(?!(?:admin|alfred)\b)[a-zA-Z\d]+)+$/
See the regex demo
If one word usernames are allowed, replace the last + (1 or more repetitions) with a ? (1 or 0 repetitions) quantifier (demo).
If you use it in AngularJS, also use ng-trim="false" to make sure leading and trailing whitespaces are not allowed.
Pattern details:
^ - start of string
(?!.*\b(?:admin|alfred)\b) - after zero or more chars (.*) there can't be admin or alfred as whole words (else, the regex will return false)
[a-zA-Z\d]+ - 1 or more alphanumerics
(?: - start of a non-capturing group
\s - a whitespace
[a-zA-Z\d]+ - 1 or more alphanumerics
)+ - end of the non-capturing group that will be repeated 1 or more times
$ - end of string.

Related

Regex creation to allow, disallow few characters

I am new to regex, i have this use case:
Allow characters, numbers.
Zero or one question mark allowed. (? - valid, consecutive question marks are not allowed (??)).
test-valid
?test - valid
??test- invalid
?test?test - valid
???test-invalid
test??test -invalid
Exlcude $ sign.
[a-zA-Z0-9?] - seems this doesn't work
Thanks.
Try the following regular expression: ^(?!.*\?\?)[a-zA-Z0-9?]+$
first we're using Negetive lookahead - which allows us to exclude any character which is followed by double question marks (Negetive lookahaed does not consume characters)
Since question mark has special meaning in regular expressions (Quantifier — Matches between zero and one times), each question mark is escaped using backslash.
The plus sign at the end is a Quantifier — Matches between one and unlimited times, as many times as possible
You can test it here
Your description can be broken down into the regex:
^(?:\??[a-zA-Z0-9])+\??$
You say characters and your description shows letters and numbers only, but it's possible \w (word characters) may be used instead - this includes underscore
It's between ^ and $ meaning the whole field must match (no partial matches, although if you want those you can remove this. The + means there must be at least one match (so empty string won't match). The capturing group ((\??[a-zA-Z0-9])) says I must either see a question mark followed by letters or just letters repeating many times, and the final question mark allows the string to end with a single question mark.
You probably don't want capturing groups here, so we can start that with ?: to prevent capture leading to:
^(?:\??[a-zA-Z0-9])+\??$
Matches
test
?test
?test?test
test?
Doesn't match
??test
???test
test??test
test??
<empty string>
?

Regex allow multiple work in a sentence

I'm trying to parse following sentences with regex (javascript) :
I wish a TV
I want some chocolate
I need fire
Currently I'm trying : I(\b[a-zA-Z]*\b){0,5}(TV|chocolate|fire) but it doesn't work. I also made some test with \w but no luck.
I want to allow any word (max 5 words) between "I" and the last word witch is predefined.
To account for non-word chars in-between words, you may use
/I(?:\W+\w+){0,5}\‌​W+(?:TV|chocolate|fir‌​e)/
See the regex demo
The point is that you added word boundaries, but did not account for spaces, punctuation, etc. (all the other non-word chars) between "words".
Pattern details:
I - matches the left delimiter
(?:\W+\w+){0,5}\‌​W+ - matches 0 to 5 sequences (due to the limiting quantifier {n,m}) of 1+ non-word chars (\W+) and 1+ word chars after them (\w+), and a \W+ at the end matches 1 or more non-word chars that must be present to separate the last matched word chars from the...
(?:TV|chocolate|fir‌​e) - matches the trailing delimiter
You need to add the whitespace after the I. Otherwise it wouldn´t capture the whole sentence.
I(\b[a-zA-Z ]*\b){0,5}(TV|chocolate|fire)
I greate site to test regex expressions is regexr
If you don't care about the spaces, use:
/I(\s[a-zA-Z]*\s?){0,5}(TV|chocolate|fire)/
Try
/I\s+(?:\w+\s+){0,5}(TV|chocolate|fire)/
(Test here)
Based on Stefan Kert version, but rely on right side spaces of each extra word instead of word boundaries.
It also accepts any valid "word" (\w) character words of any length and any valid spacing character (not caring for repetitions).

Excluding URLS that contain a string in Regex

I am using regex to add a survey to pages and I want to include it on all pages except payment and signin pages. I can't use look arounds for the regex so I am attempting to use the following but it isn't working.
^/.*[^(credit|signin)].*
Which should capture all urls except those containing credit or signin
[ indicates the start of a character class and the [^ negation is per-character. Thus your regular expression is "anything followed by any character not in this class followed by anything," which is very likely to match anything.
Since you are using specific strings, I don't think a regular expression is appropriate here. It would be a lot simpler to check that credit and signin don't exist in the string, such as with JavaScript:
-1 === string.indexOf("credit") && -1 === string.indexOf("signin")
Or you could check that a regular expression does not match
false === /credit|signin/.test(string)
Whitelisting words in regex is generally pretty easy, and usually follows a form of:
^.*(?:option1|option2).*$
The pattern breaks down to:
^ - start of string
.* - 0 or more non-newline characters*
(?: - open non-capturing group
option1|option2 - | separated list of options to whitelist
) - close non-capturing group
.* - 0 or more non-newline characters
$ - end of string
Blacklisting words in a regex is a bit more complicated to understand, but can be done with a pattern along the lines of:
^(?:(?!option1|option2).)*$
The pattern breaks down to:
^ - start of string
(?: - open non-capturing group
(?! - open negative lookahead (the next characters in the string must not match the value contained in the negative lookahead)
option1|option2 - | separated list of options to blacklist
) - close negative lookahead
. - a single non-newline character*
) - close non-capturing group
* - repeat the group 0 or more times
$ - end of string
Basically this pattern checks that the values in the blacklist do not occur at any point in the string.
* exact characters vary depending on the language, so use caution
The final version:
/^(?:(?!credit|signin).)*$/

business phone regex containing if-else expression

I am trying to write business phone number regex in javascript, my requirements are:
It should contain only digits,dashes and whitespaces
It should not end with - but can end with whitespaces
There should be only 1 - between two groups
It should match numbers with and without - like 1, 123, 678-78
I have tried following regex but it fails for 123-- as it is invalid one anybody please suggest me something
/^([ ]*[0-9]+[-]?[0-9 ]*?([-])[ ]*[0-9]+[ ]*|[0-9 ]*[ ]*)+$/.test('123--2')
Try this
/^[0-9]+(-[0-9\s]+)*$/
I don't know if you still need an answer to this, but this works for your requirements:
/^(?!.+-\s*$)\s*((?:\d+\s*-?\s*)+)$/
Explanation:
^ start of string
(?!.+-\s*$) disallow - (or - followed by whitespace) at the end of the string
\s* optional leading spaces
( start capturing
(?:\d+\s*-?\s*)+ one or more groups of the following:
one or more digits,
possibly followed by whitespace,
possibly followed by a single hyphen,
possibly followed by more whitespace
) stop capturing
$ end of the string
Demo

Regex detect chars duplicates

I use expression to detect duplicate one char in string.
if (str.replace(/[^#]/g, '').length > 1) {...}
Now, i wish detect duplicate more than one char.
For sample, lets try detect duplicates of # or #:
Wordwithone#here - match
Word#withduplicate#here - not
Word#withoneandone#here - match
Is it possible with regexp detect duplicate char from set of chars? (## as in sample)
Your attempt in the comment /([#])\1{2,}/ig will search for consecutive # in the string.
It only needs a simple modification to make it work:
/([##])[\s\S]*?\1/.test(inputString)
Either [\s\S]*? or [\s\S]* would work, just that the order of searching would be a bit different:
*? is lazy, so the search for duplicate will start from the adjacent character.
* is greedy, so the search will start from the last character in the string.
The point is to allow any number of characters to come in-between the 2 duplicates [\s\S]*. I used [\s\S] to allow any character, as opposed to . which excludes the following new line characters: \n, \r, \u2028 and \u2029.

Categories

Resources