Regex to match string with contains closed brackets - javascript

I need to create regex rule to match string with doesnt' contain ( ) character and also strings that have them inside but always closed (but not nested. Another thing that empty () is also wrong
Good strings (should be matched):
aaaaaa
(asdasd)
aaaa(bbb)a
(aaa)aaaa
aaaaaa(aaaa)
aaaa(bbb)(ccc)ddd
aaaa(bbbb)cccc(dddd)eeee
Bad strings (there shouldn't be match):
)aaaa
)aaaa(asd)
aaaaaa(
aaaa(bbb))
aaa(bbb
aaaaa((bbbb)cccc
aaaa(bbbb))ccc
aaaa(aasd(adssad))ad
adassd(aas(add)adsa(asda)ad)
()
Tried and created something like this (?!.*[(]{2,})(?!.*[)]{2,})(?![)])(?!.*[(]$).*$ but still it isn't good. Any help with this?

You can use this regex for your job:
/^(?!$)(?:[^)(]*\([^()]+\))*[^)(]*$/gm
RegEx Demo
RegEx Breakup:
^ - Line start
(?!$) - Negative lookahead to make sure we don't match empty string
(?: - Start of a non-capturing group
[^)(]* - Match 0 or more of anything but ( and )
\( - Match a (
[^()]+ - Match 1 or more of anything but ( and )
\) - Match a literal )
)* - End of the non-capturing group, * makes it match 0 or more times
[^)(]*- Match 0 or more of anything but ( and )
$ - Line end

If you want to check for balanced parens, you can use a function like this:
function balanced(str) {
var a = 0;
for(var i = 0; i < str.length; i++) { // for each character in str
if(str.charAt(i) == '(') a++; // if it's an open paren, increment a
else if(str.charAt(i) == ')') a--; // if it's a close one, decrement a
}
return a == 0; // if a == 0 then it's balanced (true), if not then it's not balanced (false)
}
var s1 = "aaaa(bbbb)cccc(dddd)eeee";
var s2 = "aaaa(bbbb(cccc(dddd)eeee";
var s3 = "aaaa";
console.log(s1 + " => " + balanced(s1));
console.log(s2 + " => " + balanced(s2));
console.log(s3 + " => " + balanced(s3));
Or if you insist on using regexp, then use two regexp to check for balanced parens like this:
function balanced(str) {
var opened = str.match(/\(/g); // match open parens
var closed = str.match(/\)/g); // match close parens
opened = opened? opened.length: 0; // get the count of opened parens, if nothing is matched then 0
closed = closed? closed.length: 0; // get the count of closed parens, if nothing is matched then 0
return opened == closed; // balanced means the count of both is equal
}
var s1 = "aaaa(bbbb)cccc(dddd)eeee";
var s2 = "aaaa(bbbb(cccc(dddd)eeee";
var s3 = "aaaa";
console.log(s1 + " => " + balanced(s1));
console.log(s2 + " => " + balanced(s2));
console.log(s3 + " => " + balanced(s3));

This should do the trick:
^([^()]|\([^()]+\))+$
reads "match not a paren or ( no parens here ), once or more, whole string"
If you want to match balanced parens at any level, a single expression is not possible in js, due to lack of recursion support, but a function will be rather trivial.
let balanced = function(s) {
var re = /\([^()]*\)/g
while (s.match(re)) s = s.replace(re, '')
return !s.match(/[()]/)
}
console.log(balanced('a(b((d))e) (f) g'))
console.log(balanced('a(b((d))e? (f) g'))
or without regexes:
let balanced = s => {
let c = 0;
for (let x of s) {
if (x == '(') c++;
if (x == ')' && !c--) return false;
}
return !c;
};

Related

Less or greater than characters except html tags?

I need to replace less or greater than(< >) characters, but keep any html tags(simple tags will do like <b>text</b> without arguments).
So the input below:
<b>> 0.5 < 0.4</b> - <>
Should be:
<b>> 0.5 < 0.4</b> - <>
All I managed to find and edit now is this expr:
<\/?[a-z][a-z0-9]*[^>\s]*>|([<>])
It groups the < and > characters but it also matches tags witch I don't need to replace
UPD:
Thanks to #Sree Kumar, here's the final functions:
String.prototype.replaceAt = function (index, char) {
let arr = this.split('');
arr[index] = char;
return arr.join('');
};
String.prototype.escape = function () {
let p = /(?:<[a-zA-Z]+>)|(?:<\/[a-zA-Z]+>)|(?<lt><)|(?<gt>>)/g,
result = this,
match = p.exec(result);
while (match !== null) {
if (match.groups.lt !== undefined) {
result = result.replaceAt(match.index, '<');
}
else if (match.groups.gt !== undefined) {
result = result.replaceAt(match.index, '>');
}
match = p.exec(result);
}
return result;
};
Here is a way to do it using named groups. That is, name your desired group and look for it. It may be null or undefined at times because it didn't match. Hence, you will have to add the null check.
Notice (?<B>...) surrounding the "desired" group. Also, notice the null check in the 5th line.
let p = /(?:<[a-zA-Z]+>)|(?:<\/[a-zA-Z]+>)|(?<B>[<>])/g
let input = '<b>> 0.5 < 0.4</b> - <>';
let match = p.exec( input );
while( match !== null) {
if( match.groups.B !== undefined ) console.log( match.groups.B );
match = p.exec( input )
}
Try this regex:
<(?!\/?\w+>)|(?<!<\w+|<\/\w+)>
Explanation
<(?!\/?\w+>) finds all '<' symbols (except in tags)
(?<!<\w+|<\/\w+)> finds all '>' symbols (except in tags)
You can use them separately:
let str = '<b>> 0.5 < 0.4</b> - <>';
let lessThen = /<(?!\/?\w+>)/g;
let greaterThen = /(?<!<\w+|<\/\w+)>/g;
str = str.replace(lessThen, '<');
str = str.replace(greaterThen, '>');
console.log(str); // <b>> 0.5 < 0.4</b> - <>
NB! It only finds symbols '<' and '>' between tags. It doesn't check that html is valid. For text like that <a></b> it will not find any matches.

Regex to Match Specific URL JavaScript

I'm trying to match a specific URL(http://www.example.me/area/?si=) that allows me to get value from si. si value will be dynamic
http://www.example.me/area/?si=4077765
Get any query string value
function qstr(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
return false;
}
Check Query String Exists
function isset_qstr(field) {
var url = vp_furl();
if (url.indexOf('?' + field + '=') != -1) {
return true;
} else if (url.indexOf('&' + field + '=') != -1) {
return true;
}
return false;
}
I think you need the first function. Vote up if you think its helpful.
Thank you. Good Luck
Assuming that the value of the si key in the query string will always be digits (ie: 0 - 9), try this...
var url = 'http://www.example.me/area/?test=4894&si=4077765&f=fjjjf',
si = url.match(/.*[\?&]si=(\d+)/i)[1];
or a little more generic...
function getQueryStringValue(url, key) {
var regex = new RegExp('.*[\\?&]' + key + '=(\\d+)', 'i');
return url.match(regex)[1];
}
if not digits try this...
/.*[\?&]si=(\w+)/i
Explanation:
.* matches any character (except newline) between 0 and unlimited times
[\?&] match a single character, either ? or &
si= matches the characters si= literally (case insensitive)
(\d+) first capturing group. matches any digit [0-9] between 1 and unlimitted times
i modifier - case insensitive
regex101
Something like that can do the trick I think:
var regex = /http\:\/\/www\.example\.me\/area\/\?si=(\w*)/;
var url = 'http://www.example.me/area/?si=4077765';
var si = url.match(regex)[1]; // si = '4077765'
The first part of the regex is simply your URL "\" is used to escape special characters.
(\d+) is a capturing group that matches all character from a-z, A-Z, 0-9, including the _ (underscore) character from 0 to n iteration.

How to add newline after a repeating pattern

Assume that there is a string like this:
var content = "1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20";
I want to add <br /> after every 5 dots.
So, the result should be:
1.2.3.4.5.<br />
6.7.8.9.10.<br />
11.12.13.14.15.<br />
16.17.18.19.20.<br />
I want to do this without a for loop. Is it possible with just regex?
i'm doing this with this code;
regenerate:function(content,call){
var data2;
var brbr = content.replace(/[\u0250-\ue007]/g, '').match(/(\r\n)/g);
if (brbr !== "") {
data2 = content.replace(/[\u0250-\ue007]/g, '').replace(/(\r\n)/gm, "<br><br>");
} else {
data2 = content.replace(/[\u0250-\ue007]/g, '');
}
var dataArr = data2.split(".");
for (var y = 10; y < dataArr.length - 10; y += 10) {
var dataArrSpecific1 = dataArr[y] + ".";
var dataArrSpecific2 = dataArr[y] + ".<br>";
var dataArrSpecificBosluk = dataArr[y + 1];
var data3 = data2.replace(new RegExp(dataArrSpecific1.replace(/[\u0250-\ue007]/g, ''), "g"), "" + dataArrSpecific2.replace(/[\u0250-\ue007]/g, '') + "");
data3 = data3.replace(new RegExp(dataArrSpecificBosluk.replace(/[\u0250-\ue007]/g, ''), "g"), " " + dataArrSpecificBosluk.replace(/[\u0250-\ue007]/g, '') + "");
data2 = data3;
}
call(data2.replace(/[\u0250-\ue007]/g, ''));
}
Actually , i want to refactoring this code
Working bin:http://jsbin.com/dikifipelo/1/
var string = "1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20." ;
string = string.replace(/(([^\.]+\.){5})/g, "$1<br/>");
Works with any type and length of characters between the dots.
Explanation:
The pattern /(([^.]+.){5})/g can be broken down as such:
[^\.] - any character that is not a dot
[^\.]+ - any character that is not a dot, one or more times
[^\.]+\. - any character that is not a dot, one or more times, followed by a dot
([^\.]+\.){5} - any character....dot, appearing five times
(([^\.]+\.){5}) - any...five times, capture this (all round brackets capture unless told not to, with a ?: as the first thing inside them)
the /g/ flag makes it so that the whole string is matched - ie, all matches are found
"$1" represents the results of the first group (or bracket)
so, the replace function finds all instances of the pattern in the string, and replaces them with the match itself + a line break (br).
Once you learn regular expressions, life is never the same.

JS Regex - Match each not escaped specific characters

I'm trying to make a Regex in JavaScript to match each not escaped specific characters.
Here I'm looking for all the ' characters. They can be at the beginning or the end of the string, and consecutive.
E.g.:
'abc''abc\'abc
I should get 3 matchs: the 1st, 5 and 6th character. But not 11th which escaped.
You'll have to account for cases like \\' which should match, and \\\' which shouldn't. but you don't have lookbehinds in JS, let alone variable-length lookbehinds, so you'll have to use something else.
Use the following regex:
\\.|(')
This will match both all escaped characters and the ' characters you're looking for, but the quotes will be in a capture group.
Look at this demo. The matches you're interested in are in green, the ones to ignore are in blue.
Then, in JS, ignore each match object m where !m[1].
Example:
var input = "'abc''abc\\'abc \\\\' abc";
var re = /\\.|(')/g;
var m;
var positions = [];
while (m = re.exec(input)) {
if (m[1])
positions.push(m.index);
}
var pos = [];
for (var i = 0; i < input.length; ++i) {
pos.push(positions.indexOf(i) >= 0 ? "^" : " ");
}
document.getElementById("output").innerText = input + "\n" + pos.join("");
<pre id="output"></pre>
You can use:
var s = "'abc''abc\\'abc";
var cnt=0;
s.replace(/\\?'/g, function($0) { if ($0[0] != '\\') cnt++; return $0;});
console.log(cnt);
//=> 3

Replace characters using Regex positive/negative lookahead?

I have this string :
var a='abc123#xyz123';
I want to build 2 regexes replace functions which :
1) Replace all characters that do have a future '#' - with '*' (not including '#')
so the result should look like :
'******#xyz123'
2) Replace all characters that do not have a future '#' - with '*' (not including '#')
so the result should look like :
'abc123#******'
What have I tried :
For the positive lookahead :
var a='abc123#xyz123';
alert(a.replace(/(.+(?=#))+/ig,'*')); //*#xyz123 --wrong result since it is greedy...
Question :
How can I make my regexes work as expected ?
First part using lookahead:
repl = a.replace(/.(?=[^#]*#)/g, "*");
//=> "******#xyz123"
Explanation:
This regex finds any character that is followed by # using lookahead and replaced that with *.
Second part using replace callback:
repla = a.replace(/#(.*)$/, function(m, t) { return m[0] + t.replace(/./g, '*'); } );
//=> abc123#******
Explanation:
This code finds text after #. Inside the callback function is replaces every character with asterisk.
You can use indexOf and substr for this instead:
function maskBeforeAfter(before, str, character, maskCharacter) {
character = character || '#';
maskCharacter = maskCharacter || '*';
var characterPosition = str.indexOf(character);
if (characterPosition > -1) {
var mask = '';
if (before) {
for (var i = 0; i < characterPosition; i++) {
mask += maskCharacter;
}
return mask + str.substr(characterPosition);
} else {
for (var i = 0; i < str.length - characterPosition - 1; i++) {
mask += maskCharacter;
}
return str.substr(0, characterPosition + 1) + mask;
}
}
return str;
}
function maskBefore(str, character, maskCharacter) {
return maskBeforeAfter(true, str, character, maskCharacter);
}
function maskAfter(str, character, maskCharacter) {
return maskBeforeAfter(false, str, character, maskCharacter);
}
> var a = 'abc12345#xyz123';
> maskBefore(a);
"********#xyz123"
> maskAfter(a);
"abc12345#******"
If you insist on a simple regex:
The first one is already answered. The second can be written similarly:
a.replace(/[^#](?![^#]*#)/g, '*')
(?![^#]*#) is a negative lookahead that checks that there isn't a pound after the current character.
[^#] also checks that the current character isn't a pound. (we could have also used /(?![^#]*#)./g, but it is less pretty.
A positive option is:
a.replace(/[^#](?=[^#]*$)/g, '*');
this is very similar to the first one: (?=[^#]*$) checks that we have only non-pounds ahead, until the end of the string.
In both of this options, all characters in strings with no pounds will be replaces: "abcd" -> "****"

Categories