regex to allow special characters but not leading/trailing white space - javascript

I would like to allow all special characters and white space in between words only for a password input field.
If whitespace entered at the leading, trailing of string, regex should fail
Any useful javascript regex?
I tried \S this does not accept any white space, would that be sufficient?
I tried \A\s|\s*\Z , but not able to negate this.

Using something like [^\s] would suffice.

The \A (start of string) and \Z (end of string) anchors are not supported by JS RegExp.
If you use /\S/ it will only match any non-whitespace char, anywhere inside a string.
If you use /^\s|\s*$/ it will match a whitespace at the start or any 0 or more whitespaces at the end.
You need
/^\S+(?:\s+\S+)*$/
See the regex demo.
It will match:
^ - start of string
\S+ - 1 or more non-whitespace chars
(?:\s+\S+)* - any 0 or more occurrences of
\s+ - 1+ whitespaces
\S+ - 1+ non-whitespace chars
$ - end of string.
JS demo:
var strs = ['Abc 123 !##', 'abc123#', ' abc34', ' a ', 'bvc '];
var rx = /^\S+(?:\s+\S+)*$/;
for (var s of strs) {
console.log("'"+s+"'", "=>", rx.test(s));
}

I don't know if it's totally fine but in your case, I think this could apply better
^((\w)*){1}$

Related

How to don't allow set only the same characters and only special sign - regex js

I'm looking for some regex pattern to:
not allow set the same characters
not allow only special signs.
So:
11111111 - not allow
1111811111 - allow
rrrrrrrr - not allow
rrrrrrrrrr5 - allow
11111111% - allow
%$!#$!#### - not allow
%%%%%%%%%1 - allow
I found regex which is helpful for recognize that string has only special sign: /^\W*\w.*$/, but I don't know how to join it with condition about not only repeated characters. Thansks for any advices.
You can assert not only the same characters and make sure to match at least a single word character.
^(?!(.)\1+$)[^\w\n]*\w.*$
Explanation
^ Start of string
(?!(.)\1+$) Negative lookahead, assert not only the same characters in the string matching at least 2 characters
[^\w\n]* Optionally match any character except a word character or newline
\w Match at least a single word character
.* Optionally match any character
$ End of string
Regex demo
const regex = /^(?!(.)\1+$)[^\w\n]*\w.*$/;
[
"11111111",
"1111811111",
"rrrrrrrr",
"rrrrrrrrrr5",
"11111111%",
"%$!#$!####",
"%%%%%%%%%1",
"a"
].forEach(s => {
if (regex.test(s)) {
console.log(s + " allow")
} else {
console.log(s + " not allow")
}
});
If you don't want to match any spaces in the string, you can match non whitespace chars using \S
^(?!(\S)\1+$)[^\w\s]*\w\S*$
Regex demo

use regex to replace spaces that occur with a value depending on how many spaces found

I want to use a regex that looks for spaces with a minimum length of 2 in a row, and replaces the occurrence with another value for each occurrence of the space found.
For example:
I love to eat cake
There are 3 spaces after love and 4 spaces after eat. I want my regex to replace occurrences of a space more than 1, and to replace it with a value for each occurrence found.
The output I am trying to go for:
I love---to eat----cake
I tried something like
myStr.replace(/ +{2,}/g, '-')
You may use this code with a lookahead and a lookbehind:
const s = 'I love to eat cake'
var r = s.replace(/ (?= )|(?<= ) /g, '-');
console.log(r);
//=> 'I love---to eat----cake'
RegEx Details:
(?= ): Match a space only if that is followed by a space
|: OR
(?<= ) : Match a space only if that is preceded by a space
You can match two or more whitespaces and replace with the same amount of hyphens:
const s = 'I love to eat cake'
console.log(s.replace(/\s{2,}/g, (x) => '-'.repeat(x.length)) )
The same approach can be used in Python (since you asked), re.sub(r'\s{2,}', lambda x: '-' * len(x.group()), s), see the Python demo.
Also, you may replace any whitespace that is followed with a whitespace char or is preceded with whitespace using
const s = 'I love to eat cake'
console.log(s.replace(/\s(?=\s|(?<=\s.))/gs, '-') )
console.log(s.replace(/\s(?=\s|(?<=\s\s))/g, '-') )
See this regex demo. Here, s flag makes . match any char. g makes the regex replace all occurrences. Also,
\s - matches any whitespace
(?=\s|(?<=\s.)) - a positive lookahead that matches a location that is immediately followed with a whitespace char (\s), or (|) if it is immediately preceded with a whitespace and any one char (which is the matched whitespace). If you use (?<=\s\s) version, there is no need of s flag, \s\s just makes sure the whitespace before the matched whitespace is checked.

Regex - I want my string to end with 2 special character

I've been trying to make a regex that ends with 2 special characters, but I couldnt find solution. Here is what i tried, but it seems like it is not working.
/.[!##$%^&*]{2}+$/;
Thanks in advance.
Try this regex:
^.*[!##$%^&*]{2}$
Demo
const regex = /^.*[!##$%^&*]{2}$/;
const str = `abc##\$`;
let m;
if(str.match(regex)) {
console.log("matched");
}
else
console.log("not matched");
The /.[!##$%^&*]{2}+$/ regex matches
. - any character but a line break char
[!##$%^&*]{2}+ - in PCRE/Boost/Java/Oniguruma and other regex engines supporting possessive quantifiers, it matches exactly 2 cars from the defined set, but in JS, it causes a "Nothing to repeat" error
$ - end of string.
To match any string ending with 2 occurrences of the chars from your defined set, you need to remove the . and + and use
console.log(/[!##$%^&*]{2}$/.test("##"))
Or, if these 2 chars cannot be preceded by a 3rd one:
console.log(/(?:^|[^!##$%^&*])[!##$%^&*]{2}$/.test("##"))
// ^^^^^^^^^^^^^^^^^
The (?:^|[^!##$%^&*]) non-capturing group matches start of string (^) or (|) any char other than !, #, #, $, %, ^, &, * ([^!##$%^&*])

Why does string.replace(/\W*/g,'_') prepend all characters?

I've been learning regexp in js an encountered a situation that I didn't understand.
I ran a test of the replace function with the following regexp:
/\W*/g
And expected it prepend the beginning of the string and proceed to replace all non-word characters.
The Number is (123)(234)
would become:
_The_Number_is__123___234_
This would be prepending the string because it has at least zero instances, and then replacing all non-breaking spaces and non-word characters.
Instead, it prepended every character and replaced all non-word characters.
_T_h_e__N_u_m_b_e_r__i_s__1_2_3__2_3_4__
Why did it do this?
The problem is the meaning of \W*. It means "0 or more non-word characters". This means that the empty string "" would match, given that it is indeed 0 non-word characters.
So the regex matches before every character in the string and at the end, hence why all the replacements are done.
You want either /\W/g (replacing each individual non-word character) or /\W+/g (replacing each set of consecutive non-word characters).
"The Number is (123)(234)".replace(/\W/g, '_') // "The_Number_is__123__234_"
"The Number is (123)(234)".replace(/\W+/g, '_') // "The_Number_is_123_234_"
TL;DR
Never use a pattern that can match an empty string in a regex replace method if your aim is to replace and not insert text
To replace all separate occurrences of a non-word char in a string, use .replace(/\W/g, '_') (that is, remove * quantifier that matches zero or more occurrences of the quantified subpattern)
To replace all chunks of non-word chars in a string with a single pattern, use .replace(/\W+/g, '_') (that is, replace * quantifier with + that matches one or more occurrences of the quantified subpattern)
Note: the solution below is tailored for the OP much more specific requirements.
A string is parsed by the JS regex engine as a sequence of chars and locations in between them. See the following diagram where I marked locations with hyphens:
-T-h-e- -N-u-m-b-e-r- -i-s- -(-1-2-3-)-(-2-3-4-)-
||| |
||Location between T and h, etc. ............. |
|1st symbol |
start -> end
All these positions can be analyzed and matched with a regex.
Since /\W*/g is a regex matching all non-overlapping occurrences (due to g modifier) of 0 and more (due to * quantifier) non-word chars, all the positions before word chars are matched. Between T and h, there is a location tested with the regex, and as there is no non-word char (h is a word char), the empty match is returned (as \W* can match an empty string).
So, you need to replace the start of string and each non-word char with a _. Naive approach is to use .replace(/\W|^/g, '_'). However, there is a caveat: if a string starts with a non-word character, no _ will get appended at the start of the string:
console.log("Hi there.".replace(/\W|^/g, '_')); // _Hi_there_
console.log(" Hi there.".replace(/\W|^/g, '_')); // _Hi_there_
Note that here, \W comes first in the alternation and "wins" when matching at the beginning of the string: the space is matched and then no start position is found at the next match iteration.
You may now think you can match with /^|\W/g. Look here:
console.log("Hi there.".replace(/^|\W/g, '_')); // _Hi_there_
console.log(" Hi there.".replace(/^|\W/g, '_')); // _ Hi_there_
The _ Hi_there_ second result shows how JS regex engine handles zero-width matches during a replace operation: once a zero-width match (here, it is the position at the start of the string) is found, the replacement occurs, and the RegExp.lastIndex property is incremented, thus proceeding to the position after the first character! That is why the first space is preserved, and no longer matched with \W.
A solution is to use a consuming pattern that will not allow zero-width matches:
console.log("Hi there.".replace(/^(\W?)|\W/g, function($0,$1) { return $1 ? "__" : "_"; }));
console.log(" Hi there.".replace(/^(\W?)|\W/g, function($0,$1) { return $1 ? "__" : "_"; }));
You can use RegExp /(^\W*){1}|\W(?!=\w)/g to match one \W at beginning of string or \W not followed by \w
var str = "The Number is (123)(234)";
var res = str.replace(/(^\W*){1}|\W(?!=\w)/g, "_");
console.log(res);
You should have used /\W+/g instead.
"*" means all characters by itself.
It's because you're using the * operator. That matches zero or more characters. So between every character matches. If you replace the expression with /\W+/g it works as you expected.
This should work for you
Find: (?=.)(?:^\W|\W$|\W|^|(.)$)
Replace: $1_
Cases explained:
(?= . ) # Must be at least 1 char
(?: # Ordered Cases:
^ \W # BOS + non-word (consumes bos)
| \W $ # Non-word + EOS (consumes eos)
| \W # Non-word
| ^ # BOS
| ( . ) # (1), Any char + EOS
$
)
Note this could have been done without the lookahead via
(?:^\W|\W$|\W|^$)
But, this will insert a single _ on an empty string.
So, it ends up being more elaborate.
All in all though, it's a simple replacement.
Unlike Stribnez's solution, no callback logic is required
on the replace side.

How to know if there are non-whitespace char before the target string?

How do i express this in regex to know if there are non-whitespace chars before '#include'?
var kword_search = "#include<iostream.>something";
/^?+\s*#include$/.test(kword_search)//must return false
var kword_search = "asffs#include<iostream.>something";
/^?+\s*#include$/.test(kword_search)//must return true
Not really good in regex
You are likely looking for something like /^[\S ]#include/
Explanation:
^ beginning of the string
[\S ] any character of: non-whitespace (all but
\n, \r, \t, \f, and " "), ' '
#include/ '#include/'
Regex quick reference
[abc] A single character: a, b or c
[^abc] Any single character but a, b, or c
[a-z] Any single character in the range a-z
[a-zA-Z] Any single character in the range a-z or A-Z
^ Start of line
$ End of line
\A Start of string
\z End of string
. Any single character
\s Any whitespace character
\S Any non-whitespace character
\d Any digit
\D Any non-digit
\w Any word character (letter, number, underscore)
\W Any non-word character
\b Any word boundary character
(...) Capture everything enclosed
(a|b) a or b
? Zero or one
* Zero or more
+ One or more
Use negated character class, with appropriate quantifier. And remove the $ anchor from the end, your string doesn't end with include:
/^[^\s]+#include/.test(kword_search)
/^(?:\s*|)#include/.test(kword_search)
Simply:
\S#include
See a live demo passing your tests on jsfiddle

Categories

Resources