I have this regex:
/(((\w+)|(\.\w+)|(\#\w+)|\*)(\[(.+(=".+"|\*".+"|\^".+"|))\])?(::|:)?)+(?=[ \S]*\{)/gm
Which I am trying to use to match CSS selectors. Consider this pseudo-code CSS input:
.main {
property: value;
}
.one, .two a[href$=".com"] {
.subclass {
property: value;
}
}
.test:before, .test:after:active {}
The pattern above will return the following matches:
['.body', '.one', '.two', 'a[href$=".com"]', '.subclass', '.test:before', '.test:after:active']
I am trying to modify the pattern so that psuedo selectors are not matched. So all the other matches should still be valid, but .test:before should just be .test and .test:after:active should also just match .test. I can't think of a way to do this without either a negative look-behind, or a way to not match if the first character is a :.
I'm implementing this in Node, and I don't want to lock my script to Node > 9.2.0 just to use negative look-behinds in my regex.
Any ideas would be greatly appreciated!
(?!.*:)(?:[.#]\w+|\w+\[.*\])
You could use something like this?
This uses a negative lookahead to ensure it doesn't capture anything with a colon beside it, as well as using a simplified version of your matcher for psuedo css elements.
See it working here
Related
I'm trying to write a regular expression that matches filenames, such as:
image.png
image.svg
image.gif
However, I don't want it to match if my extension is preceded by .inline, like so:
image.inline.png
image.inline.svg
image.inline.gif
My current regular expression matches the first three, and is like so: /\.(gif|png|svg)$/ - however, I'm having trouble adding in the negative condition for a preceding .inline.
Thanks in advance for any advice.
I would also use a negative lookahead, but I would phrase it slightly differently:
var term = "image.inline.png";
var re = new RegExp("^(?!.*\\.inline\\.[^.]+$).*\\.(?:gif|png|svg)$");
if (re.test(term)) {
console.log("Valid");
} else {
console.log("Invalid");
}
You can use a negative lookahead to check for the preceeding .inline. See it in action here.
^\w+(?!\.inline)\.(gif|png|svg)$
I need to match the text between two brackets. many post are made about it but non are supported by JavaScript because they all use the lookbehind.
the text is as followed
"{Code} - {Description}"
I need Code and Description to be matched with out the brackets
the closest I have gotten is this
/{([\s\S]*?)(?=})/g
leaving me with "{Code" and "{Description" and I followed it with
doing a substring.
so... is there a way to do a lookbehind type of functionality in Javascript?
You could simply try the below regex,
[^}{]+(?=})
Code:
> "{Code} - {Description}".match(/[^}{}]+(?=})/g)
[ 'Code', 'Description' ]
Use it as:
input = '{Code} - {Description}';
matches = [], re = /{([\s\S]*?)(?=})/g;
while (match = re.exec(input)) matches.push(match[1]);
console.log(matches);
["Code", "Description"]
Actually, in this particular case, the solution is quite easy:
s = "{Code} - {Description}"
result = s.match(/[^{}]+(?=})/g) // ["Code", "Description"]
Have you tried something like this, which doesn't need a lookahead or lookbehind:
{([^}]*)}
You would probably need to add the global flag, but it seems to work in the regex tester.
The real problem is that you need to specify what you want to capture, which you do with capture groups in regular expressions. The part of the matched regular expression inside of parentheses will be the value returned by that capture group. So in order to omit { and } from the results, you just don't include those inside of the parentheses. It is still necessary to match them in your regular expression, however.
You can see how to get the value of capture groups in JavaScript here.
I am using this regex /\s*?left:\s*?-?\d+\.?\d*px;/im to find for example: left: 100.5px;.
The problem is that it also finds margin-left: 100px; or padding-left... I want it to not match words like -left but match left.
Any ideas?
EDIT: I am using this with javascript. I have made a simple jsfiddle for this. http://jsfiddle.net/WU7GV/3/ The goal is make "jupp" appear, but not "nope" with the same regex in both if-sentences
Option 1: Use start anchor:
/^left:\s*-?\d+\.?\d*px;/im
Option 2: If you cannot use start anchor as this might not be the actual start of input text then you can use word boundary with negative lookbehind like this:
/(?<!-)\bleft:\s*-?\d+\.?\d*px;/im
Live Demo: http://www.rubular.com/r/o1lsRU9mmE
Update: Javascript workaround for absence of negative lookahead:
var re=/\b.*?(left:\s*-?\d+\.?\d*px;)/igm;
function matchIt(str) {
repl = str.replace(re, function($0, $1) {
return $0 == $1? $0 : '';
});
return repl != ""? true : false;
}
console.log(matchIt('margin-left:100px;')); // false
console.log(matchIt('left:100px;')); // true
Live Demo: http://ideone.com/xt1kPH
Use a start-of-expression anchor
/^\s*?left:\s*?-?\d+\.?\d*px;/im
There can also be metrics other than px, but I'm sure you know that.
Use a beginning of string (and ending) anchor, like this:
/^\s*?left:\s*?-?\d+\.?\d*px;$/im
Use Word Boundries:
[^(left)]*\b\s*?(left:\s*?-?\d+\.?\d*px;)
So it looks for anything that isn't 'left', a word boundry, as described in the link above. Then your (group) to return what you want.
If you specify what language this regex is in, it'll help us answer your question. Otherwise, try out www.debuggex.com for an interactive regex debugger!
Try using this regex:
/([^-]left|^left):.*?;/im
This will match in case your string begins with "left" or one that contains "left" but not "-left".
If you aren't concerned with the units of your style, .*?; is a good shorthand to match everything from : to the nearest ; .
If you need to only match px and not %;, pt;, em !important;, etc..., keep your same regex after :, although I think the non-greedy spaces:
\s*?
are unnecessary, i.e., you could just use:
/([^-]left|^left):\s*-?\d+\.?\d*px;/im
Let's say I have the following string:
ZD:123123 ZD:213123 ZD:2e213 [ZD:213123] [ZD#221313] ZD:234...
I want to pattern match every occurrence except ZD:234... because I don't want any words that have an elipses.
This pattern was doing nicely for me in JavaScript:
/(\[|\(|)ZD[:#]\w+(\]|\)|)/g
However, it still captures the ZD:234 part of ZD:234... which I absolutely don't want it to do.
How can I prevent regex from doing this?
An easy fix is to use a negative lookahead:
/(\[|\(|)ZD[:#]\w+\b(\]|\)|)(?!\.\.\.)/g
Note that I've also added \b to avoid matching on ZD:23.
A bit simplified:
/[\[(]?ZD[:#]\w+\b[\])]?(?!\.\.\.)/g
In case you want matching brackets (no [ZD:123)):
/(?:ZD[:#]\w+|\[ZD[:#]\w+\]|\(ZD[:#]\w+\))\b(?!\.\.\.)/g
There is more than one way to skin a cat. The following will work in more browsers by using a simpler regular expression:
function trim(s) {
return s.replace(/^ | $/g,'').replace(/\s+/g,' ');
}
var x = 'ZD:123123 ZD:213123 ZD:2e213... [ZD:213123] [ZD#221313] ZD:234...';
alert(
trim(x.replace(/(^| )[^ ]+[\.]{3}( |$)/g,' ')).split(/\s+/)
);
/* shows: ZD:123123,ZD:213123,[ZD:213123],[ZD#221313] */
It removes any space delimited "word" of characters ending in ... and then splits on the space.
I have a javascript function that looks element id with certain patterns. So I have the following script:
if (f.elements[i].id.match(/DataList\[-\d{3}|\d{3}\]\.MemberId/)) {
//do something
}
It should match elements with ids such as these:
DataList[-1].MemberId
DataList[-2].MemberId
And it does, however it also matches the following:
DataList[-1].FirstName
DataList[-2].FirstName
which I don't want.
Could any guru take a look at the regular expression above and point out what is going wrong?
Thanks,
Cullen
Try to anchor your regex at the beginning with a ^ and at the end with a $, group your digit match and allow 1-3 digits instead of just 3.
if (f.elements[i].id.match(/^DataList\[(-\d{1,3}|\d{1,3})\]\.MemberId$/)) {
//do something
}
The way you had it, it was matching anything containing "DataList[-123" or containing "123].MemberId".
A simpler overall regex that accomplishes the same thing is:
if (f.elements[i].id.match(/^DataList\[-?\d{1,3}\]\.MemberId$/)) {
//do something
}
The or is saying:
DataList\[-\d{3} OR \d{3}\]\.MemberId/
This regex matches correctly:
DataList\[-?\d{1,3}\]\.MemberId
My suggestion
if (f.elements[i].id.match(/DataList\[-[0-9]{1,3}\]\.MemberId/)) {
}
The {} determines how many #s you want to support so 1-3 would match upu to [999]