regex to match all words but AND, OR and NOT - javascript

In my javascript app I have this random string:
büert AND NOT 3454jhadf üasdfsdf OR technüology AND (bar OR bas)
and i would like to match all words special chars and numbers besides the words AND, OR and NOT.
I tried is this
/(?!AND|OR|NOT)\b[\u00C0-\u017F\w\d]+/gi
which results in
["büert", "3454jhadf", "asdfsdf", "technüology", "bar", "bas"]
but this one does not match the ü or any other letter outside the a-z alphabet at the beginning or at the end of a word because of the \b word boundary.
removing the \b oddly ends up matching part or the words i would like to exclude:
/(?!AND|OR|NOT)[\u00C0-\u017F\w\d]+/gi
result is
["büert", "ND", "OT", "3454jhadf", "üasdfsdf", "R", "technüology", "ND", "bar", "R", "bas"]
what is the correct way to match all words no matter what type of characters they contain besides the ones i want exclude?

The issue here has its roots in the fact that \b (and \w, and other shorthand classes) are not Unicode-aware in JavaScript.
Now, there are 2 ways to achieve what you want.
1. SPLIT WITH PATTERN(S) YOU WANT TO DISCARD
var re = /\s*\b(?:AND|OR|NOT)\b\s*|[()]/;
var s = "büert AND NOT 3454jhadf üasdfsdf OR technüology AND (bar OR bas)";
var res = s.split(re).filter(Boolean);
document.body.innerHTML += JSON.stringify(res, 0, 4);
// = > [ "büert", "3454jhadf üasdfsdf", "technüology", "bar", "bas" ]
Note the use of a non-capturing group (?:...) so as not to include the unwanted words into the resulting array. Also, you need to add all punctuation and other unwanted characters to the character class.
2. MATCH USING CUSTOM BOUNDARIES
You can use groupings with anchors/reverse negated character class in a regex like this:
(^|[^\u00C0-\u017F\w])(?!(?:AND|OR|NOT)(?=[^\u00C0-\u017F\w]|$))([\u00C0-\u017F\w]+)(?=[^\u00C0-\u017F\w]|$)
The capure group 2 will hold the values you need.
See regex demo
JS code demo:
var re = /(^|[^\u00C0-\u017F\w])(?!(?:AND|OR|NOT)(?=[^\u00C0-\u017F\w]|$))([\u00C0-\u017F\w]+)(?=[^\u00C0-\u017F\w]|$)/gi;
var str = 'büert AND NOT 3454jhadf üasdfsdf OR technüology AND (bar OR bas)';
var m;
var arr = [];
while ((m = re.exec(str)) !== null) {
arr.push(m[2]);
}
document.body.innerHTML += JSON.stringify(arr);
or with a block to build the regex dynamically:
var bndry = "[^\\u00C0-\\u017F\\w]";
var re = RegExp("(^|" + bndry + ")" + // starting boundary
"(?!(?:AND|OR|NOT)(?=" + bndry + "|$))" + // restriction
"([\\u00C0-\\u017F\\w]+)" + // match and capture our string
"(?=" + bndry + "|$)" // set trailing boundary
, "g");
var str = 'büert AND NOT 3454jhadf üasdfsdf OR technüology AND (bar OR bas)';
var m, arr = [];
while ((m = re.exec(str)) !== null) {
arr.push(m[2]);
}
document.body.innerHTML += JSON.stringify(arr);
Explanation:
(^|[^\u00C0-\u017F\w]) - our custom boundary (match a string start with ^ or any character outside the [\u00C0-\u017F\w] range)
(?!(?:AND|OR|NOT)(?=[^\u00C0-\u017F\w]|$)) - a restriction on the match: the match is failed if there are AND or OR or NOT followed by string end or characters other than those in the \u00C0-\u017F range or non-word character
([\u00C0-\u017F\w]+) - match word characters ([a-zA-Z0-9_]) or those from the \u00C0-\u017F range
(?=[^\u00C0-\u017F\w]|$) - the trailing boundary, either string end ($) or characters other than those in the \u00C0-\u017F range or non-word character.

Related

Regex replace all character except last 5 character and whitespace with plus sign

I wanted to replace all characters except its last 5 character and the whitespace with +
var str = "HFGR56 GGKDJ JGGHG JGJGIR"
var returnstr = str.replace(/\d+(?=\d{4})/, '+');
the result should be "++++++ ++++ +++++ JGJGIR" but in the above code I don't know how to exclude whitespace
You need to match each character individually, and you need to allow a match only if more than six characters of that type follow.
I'm assuming that you want to replace alphanumeric characters. Those can be matched by \w. All other characters will be matched by \W.
This gives us:
returnstr = str.replace(/\w(?=(?:\W*\w){6})/g, "+");
Test it live on regex101.com.
The pattern \d+(?=\d{4}) does not match in the example string as is matches 1+ digits asserting what is on the right are 4 digits.
Another option is to match the space and 5+ word characters till the end of the string or match a single word character in group 1 using an alternation.
In the callback of replace, return a + if you have matched group 1, else return the match.
\w{5,}$|(\w)
Regex demo
let pattern = / \w{5,}$|(\w)/g;
let str = "HFGR56 GGKDJ JGGHG JGJGIR"
.replace(pattern, (m, g1) => g1 ? '+' : m);
console.log(str);
Another way is to replace a group at a time where the number of +
replaced is based on the length of the characters matched:
var target = "HFGR56 GGKDJ JGGHG JGJGIR";
var target = target.replace(
/(\S+)(?!$|\S)/g,
function( m, g1 )
{
var len = parseInt( g1.length ) + 1;
//return "+".repeat( len ); // Non-IE (quick)
return Array( len ).join("+"); // IE (slow)
} );
console.log ( target );
You can use negative lookahead with string end anchor.
\w(?!\w{0,5}$)
Match any word character which is not followed by 0 to 5 characters and end of string.
var str = "HFGR56 GGKDJ JGGHG JGJGIR"
var returnstr = str.replace(/\w(?!\w{0,5}$)/g, '+');
console.log(returnstr)

Javascript Regex to split line of log with key value pairs

I have a log like
t=2016-08-03T18:47:26+0000 lvl=dbug msg="Event Received" Service=SomeService
and I want to turn it into a javascript object like
{
t: 2016-08-03T18:47:26+0000,
lvl: dbug
msg: "Event Received"
Service: SomeService
}
But I am having trouble coming up with a regex that will detect the string "Event Received" in the log line.
I want to split the log line by space but because of the string it is much more difficult.
I am trying to come up with a regex that will detect the fields and parameters so that I can isolate them and split with the equal sign.
I suggest a regex without any lookahead:
var re = /(\w+)=(?:"([^"]*)"|(\S*))/g;
See the regex demo
The point is that the first group ((\w+)) captures the attribute name and the 2nd and 3rd are placed into a non-capturing "container" as alternative branches. Their values can be checked and then either one will be used to fill out the object.
Pattern details:
(\w+) - Group 1 (attribute name) matching 1+ word chars (from [a-zA-Z0-9_] ranges)
= - an equal sign
(?:"([^"]*)"|(\S*)) - a non-capturing "container" group matching either of the two alternatives:
"([^"]*)" - a quote, then Group 2 capturing 0+ chars other than ", and a quote
| - or
(\S*) - Group 3 capturing 0+ non-whitespace symbols.
var rx = /(\w+)=(?:"([^"]*)"|(\S*))/g;
var s = "t=2016-08-03T18:47:26+0000 lvl=dbug msg=\"Event Received\" Service=SomeService";
var obj = {};
while((m=rx.exec(s))!==null) {
if (m[2]) {
obj[m[1]] = m[2];
} else {
obj[m[1]] = m[3];
}
}
console.log(obj);
You can use this regex to capture various name=value pairs:
/(\w+)=(.*?)(?= \w+=|$)/gm
RegEx Demo
Code:
var re = /(\w+)=(.*?)(?= \w+=|$)/gm;
var str = 't=2016-08-03T18:47:26+0000 lvl=dbug msg="Event Received" Service=SomeService';
var m;
var result = {};
while ((m = re.exec(str)) !== null) {
if (m.index === re.lastIndex)
re.lastIndex++;
result[m[1]] = m[2];
}
console.log(result);
Use this pattern:
/^t=([^ ]+) lvl=([^ ]+) msg=(.*?[a-z]") Service=(.*)$/gm
Online Demo
To achieve expected result, use below
var x = 't=2016-08-03T18:47:26+0000 lvl=dbug msg="Event Received" Service=SomeService';
var y = x.replace(/=/g,':').split(' ');
var z = '{'+ y+'}';
console.log(z);
http://codepen.io/nagasai/pen/oLPRAy

Javascript regexp capture matches delimited by character

I have a string like
classifier1:11:some text1##classifier2:fdglfgfg##classifier3:fgdfgfdg##classifier4
I am trying to capture terms like classifier1:11, classifier2:, classifier3 and classifier4
So these classifiers can be followed by a single semicolon or not.
So far I came up with
/([^#]*)(?::(?!:))/g
But that does not seem to capture classifier4, not sure what I am missing here
It seems that a classifier in your case consists of any word chars that may have single : in between and ends with a digit.
Thus, you may use
/(\w+(?::+\w+)*\d)[^#]*/g
See the regex demo
Explanation:
(\w+(?::+\w+)*\d) - Group 1 capturing
\w+ - 1 or more [a-zA-Z0-9_] (word) chars
(?::+\w+)* - zero or more sequences of 1+ :s and then 1+ word chars
\d - a digit should be at the end of this group
[^#]* - zero or more characters other than the delimiter #.
JS:
var re = /(\w+(?::+\w+)*\d)[^#\n]*/g;
var str = 'classifier4##classifier1:11:some text1##classifier2:fdglfgfg##classifier3:fgdfgfdg\nclassifier1:11:some text1##classifier4##classifier2:fdglfgfg##classifier3:fgdfgfdg##classifier4';
var res = [];
while ((m = re.exec(str)) !== null) {
res.push(m[1]);
}
document.body.innerHTML = "<pre>" + JSON.stringify(res, 0, 4) + "</pre>";
Basing on your pattern you can use a regex like this:
([^#]*)(?::|$)
Working demo

Regular Expression Url Address

My URL String:
https://stackoverflow.com/questions
My regex : [\w.]+
Result: ["http","stackoverflow.com","questions"]
How I ignore .* in stackoverflow.com only one regex.
Result I want: ["http","stackoverflow","questions"]
You can use this regex that captures into Group 1 all alphanumeric/underscore chunks that are not preceded with .:
/(?:^|[^.])\b(\w+)\b/g
See the regex demo.
Breakdown:
(?:^|[^.]) - matches (but does not store in a group buffer) the beginning of a string or any character but a literal dot
\b - leading word boundary
(\w+) - Group 1 capturing one or more word characters
\b - trailing word boundary
Sample code:
var re = /(?:^|[^.])\b(\w+)\b/g;
var str = 'http://stackoverflow.com/questions';
var res = [];
while ((m = re.exec(str)) !== null) {
res.push(m[1]);
}
document.body.innerHTML = "<pre>" + JSON.stringify(res, 0, 4) + "</pre>";
Another solution based on the assumption the word character should not be followed with /:
\b\w+\b(?!\/)
See another regex demo
var re = /\b\w+\b(?!\/)/g;
var str = 'http://stackoverflow.com/questions';
var res = str.match(re);
document.body.innerHTML = "<pre>" + JSON.stringify(res, 0, 4) + "</pre>";
Note that both solutions require a word boundary to work properly, just a negated character class (#1) or a lookahead (#2) won't work by themselves (partial matches will be rejected thanks to \b).

Javascript split by spaces but not those in quotes

The goal is to split a string at the spaces but not split the text data that is in quotes or separate that from the adjacent text.
The input is effectively a string that contains a list of value pairs. If the value value contains a space it is enclosed in quotes. I need a function that returns an array of value-pair elements as per the example below:
Example Input:
'a:0 b:1 moo:"foo bar" c:2'
Expected result:
a:0,b:1,moo:foo bar,c:2 (An array of length 4)
I have checked through a load of other questions but none of them (I found) seem to cope with my issue. Most seem to split at the space within the quotes or they split the 'moo:' and 'foo bar' into separate parts.
Any assistance would be greatly appreciated,
Craig
You can use this regex for split:
var s = 'a:0 b:1 moo:"foo bar" c:2';
var m = s.split(/ +(?=(?:(?:[^"]*"){2})*[^"]*$)/g);
//=> [a:0, b:1, moo:"foo bar", c:2]
RegEx Demo
It splits on spaces only if it is outside quotes by using a positive lookahead that makes sure there are even number of quotes after a space.
You could approach it slightly differently and use a Regular Expression to split where spaces are followed by word characters and a colon (rather than a space that's not in a quoted part):
var str = 'a:0 b:1 moo:"foo bar" c:2',
arr = str.split(/ +(?=[\w]+\:)/g);
/* [a:0, b:1, moo:"foo bar", c:2] */
Demo jsFiddle
What's this Regex doing?
It looks for a literal match on the space character, then uses a Positive Lookahead to assert that the next part can be matched:
[\w]+ = match any word character [a-zA-Z0-9_] between one and unlimited times.
\: = match the : character once (backslash escaped).
g = global modifier - don't return on first match.
Demo Regex101 (with explanation)
Any special reason it has to be a regexp?
var str = 'a:0 b:1 moo:"foo bar" c:2';
var parts = [];
var currentPart = "";
var isInQuotes= false;
for (var i = 0; i < str.length, i++) {
var char = str.charAt(i);
if (char === " " && !isInQuotes) {
parts.push(currentPart);
currentPart = "";
} else {
currentPart += char;
}
if (char === '"') {
isInQuotes = !isInQuotes;
}
}
if (currentPart) parts.push(currentPart);

Categories

Resources