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

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 !, #, #, $, %, ^, &, * ([^!##$%^&*])

Related

Javascript how to identify a combination of letters and strip a portion of it

Im very new to Regex . Right now im trynig to use regex to prepare my markup string before sending it to the database.
Here is an example string:
#[admin](user:3) Testing this string #[hellotessginal](user:4) Hey!
So far i am able to identify #[admin](user:3) the entire term here using /#\[(.*?)]\((.*?):(\d+)\)/g
But the next step forward is that i wish to remove the (user:3) leaving me with #[admin].
Hence the result of passing through the stripper function would be:
#[admin] Testing this string #[hellotessginal] Hey!
Please help!
You may use
s.replace(/(#\[[^\][]*])\([^()]*?:\d+\)/g, '$1')
See the regex demo. Details:
(#\[[^\][]*]) - Capturing group 1: #[, 0 or more digits other than [ and ] as many as possible and then ]
\( - a ( char
[^()]*? - 0 or more (but as few as possible) chars other than ( and )
: - a colon
\d+ - 1+ digits
\) - a ) char.
The $1 in the replacement pattern refers to the value captured in Group 1.
See the JavaScript demo:
const rx = /(#\[[^\][]*])\([^()]*?:\d+\)/g;
const remove_parens = (string, regex) => string.replace(regex, '$1');
let s = '#[admin](user:3) Testing this string #[hellotessginal](user:4) Hey!';
s = remove_parens(s, rx);
console.log(s);
Try this:
var str = "#[admin](user:3) Testing this string #[hellotessginal](user:4) Hey!";
str = str.replace(/ *\([^)]*\) */g, ' ');
console.log(str);
You can replace matches of the following regular expression with empty strings.
str.replace(/(?<=\#\[(.*?)\])\(.*?:\d+\)/g, ' ');
regex demo
I've assumed the strings for which "admin" and "user" are placeholders in the example cannot contain the characters in the string "()[]". If that's not the case please leave a comment and I will adjust the regex.
I've kept the first capture group on the assumption that it is needed for some unstated purpose. If it's not needed, remove it:
(?<=\#\[.*?\])\(.*?:\d+\)
There is of course no point creating a capture group for a substring that is to be replaced with an empty string.
Javascript's regex engine performs the following operations.
(?<= : begin positive lookbehind
\#\[ : match '#['
(.*?) : match 0+ chars, lazily, save to capture group 1
\] : match ']'
) : end positive lookbehind
\(.*?:\d+\) : match '(', 0+ chars, lazily, 1+ digits, ')'

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

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}$

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.

regular expression, not reading entire string

I have a standard expression that is not working correctly.
This expression is supposed to catch if a string has invalid characters anywhere in the string. It works perfect on RegExr.com but not in my tests.
The exp is: /[a-zA-Z0-9'.\-]/g
It is failing on : ####
but passing with : aa####
It should fail both times, what am I doing wrong?
Also, /^[a-zA-Z0-9'.\-]$/g matches nothing...
//All Boxs
$('input[type="text"]').each(function () {
var text = $(this).prop("value")
var textTest = /[a-zA-Z0-9'.\-]/g.test(text)
if (!textTest && text != "") {
allFieldsValid = false
$(this).css("background-color", "rgba(224, 0, 0, 0.29)")
alert("Invalid characters found in " + text + " \n\n Valid characters are:\n A-Z a-z 0-9 ' . -")
}
else {
$(this).css("background-color", "#FFFFFF")
$(this).prop("value", text)
}
});
edit:added code
UPDATE AFTER QUESTION RE-TAGGING
You need to use
var textTest = /^[a-zA-Z0-9'.-]+$/.test(text)
^^
Note the absence of /g modifier and the + quantifier. There are known issues when you use /g global modifier within a regex used in RegExp#test() function.
You may shorten it a bit with the help of the /i case insensitive modifier:
var textTest = /^[A-Z0-9'.-]+$/i.test(text)
Also, as I mention below, you do not have to escape the - at the end of the character class [...], but it is advisable to keep escaped if the pattern will be modified later by less regex-savvy developers.
ORIGINAL C#-RELATED DETAILS
Ok, say, you are using Regex.IsMatch(str, #"[a-zA-Z0-9'.-]"). The Regex.IsMatch searches for partial matches inside a string. So, if the input string contains an ASCII letter, digit, ', . or -, this will pass. Thus, it is logical that aa#### passes this test, and #### does not.
If you use the second one as Regex.IsMatch(str, #"^[a-zA-Z0-9'.-]$"), only 1 character strings (with an optional newline at the end) would get matched as ^ matches at the start of the string, [a-zA-Z0-9'.-] matches 1 character from the specified ranges/sets, and $ matches the end of the string (or right before the final newline).
So, you need a quantifier (+ to match 1 or more, or * to match zero or more occurrences) and the anchors \A and \z:
Regex.IsMatch(str, #"\A[a-zA-Z0-9'.-]+\z")
^^ ^^^
\A matches the start of string (always) and \z matches the very end of the string in .NET. The [a-zA-Z0-9'.-]+ will match 1+ characters that are either ASCII letters, digits, ', . or -.
Note that - at the end of the character class does not have to be escaped (but you may keep the \- if some other developers will have to modify the pattern later).
And please be careful where you test your regexps. Regexr only supports JavaScript regex syntax. To test .NET regexps, use RegexStorm.net or RegexHero.
/^[a-zA-Z0-9'.-]+$/g
In the second case your (/[a-zA-Z0-9'.-]/g) was working because it matched on the first letter, so to make it correct you need to match the whole string (use ^ and $) and also allow more letters by adding a + or * (if you allow empty string).
Try this regex it matches any char which isn't part of the allowed charset
/[^a-zA-Z0-9'.\-]+/g
Test
>>regex = /[^a-zA-Z0-9'.\-]+/g
/[^a-zA-Z0-9'.\-]+/g
>>regex.test( "####dsfdfjsakldfj")
true
>>regex.test( "dsfdfjsakldfj")
false

JS Regex lookahead

I want to be able to match these types of strings (comma separated, and no beginning or trailing spaces):
LaunchTool[0].Label,LaunchTool[0].URI,LaunchTool[1].Label,LaunchTool[1].URI,LaunchItg[0].Label,LaunchItg[0].URI,csr_description
The rules, in English, are:
1) Zero or more instances of [] where the brackets must contain only one number 0-9
2) Zero or more instances of ., where . must be followed by a letter
3) Zero or more instances of _, where _ must be followed by a letter
I currently have this regex:
/^([a-z]){1,}(\[[0-9]\]){0,}(\.){0,}[a-z]{1,}$/i
I cannot figure out why
"aaaa" doesn't match
furthemore,
"aaaa[0].a" matches, but "aaaa[0]" does not...
anyone know what's wrong? I believe I might need a lookahead to make sure . and _ characters are followed by a letter? Perhaps I can avoid it.
this regex can match "aaaa", try getting value of
(/^([a-z]){1,}(\[[0-9]\]){0,}(\.){0,}[a-z]{1,}$/i).test("aaaa")
"aaaa[0]" does not match, because there is [a-z]{1,} in the end of expression. once "[0]" is matched by (\[[0-9]\]){0,}, trailing [a-z]{1,} must be shown at the end of string
Use optional capture groups. Example: ([a-z])?.
Here is what i ended up with:
/^((\w+)(\[\d+\])?\.?(\w+)?,?)+$/
Shorthands explanation:
* = {0,}
+ = {1,}
\w = [A-Za-z0-9_]
\d = [0-9]

Categories

Resources