Negative match for earlier part of a regular expression - javascript

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

Related

Regex - conditional match for hyphened appendices

I'm dealing with 8 character jobnames that must follow convention, but I want to allow additional characters if appended with a hyphen.
I have come up with this:
\w{2}YYY\w{3}(?(-).*|\b)
Which matches correctly:
XXYYY001 >> match
XXYYY001-TEST >> match
XXYYY001123 >> no match
This seems cumbersome however, so I just wanna know the most efficient expression.
EDIT: Thanks Wiktor, your answer worked.
And to take it one step further: If I wanted to use a variable for YYY?
Like this.
explanation:
^ matches beginning of string
\w{2}YYY\w{3} is the part you wrote. Matches main pattern
(\-.*) matches a dash, followed by anything (including nothing. see test #4)
? Means the previous match can occur zero or one times
const pattern = /^\w{2}YYY\w{3}(\-.*)?$/;
const strings = [
'XXYYY001',
'XXYYY001XXXTEST',
'XXYYY001-TEST',
'XXYYY003-',
'FARFXXYYY003',
'FARFXXYYY003-TEST'
];
strings.forEach(string => {
let conforms = pattern.test(string);
console.log(string,conforms);
});

Regular expression matching URL parameters

Given the following two strings
?room=any_characters123&name=John
?room=any_characters123
I want to extract "any_characters123" using regular expression.
I've tried
(?<=room=)(\w)+(?=\&)
but this one fails on the second string (because the matched string must end with "&").
How can I edit my regular expression so that it matches any_characters123 in both strings?
Since javascript won't support lookbehinds, you need to use capturing group.
\?room=(\w+)
Example:
> var s = "?room=any_characters123&name=John"
> var s1 = "?room=any_characters123"
undefined
> var re = /\?room=(\w+)/;
undefined
> console.log(re.exec(s)[1])
any_characters123
undefined
> console.log(re.exec(s1)[1])
any_characters123
If you're using JS, lookbehind is not supported. You can modify the regex as follows:
room=([^&]+)
Try putting * in the end of your expression:
room=(\w+)\&*?
It will test for zero or plus ocurrences of &
This should do the trick:
/room=(\w+)&?/
/*
find "room=" then match any word characters (at least one) until you
possibly hit "&"
*/
Example:
/room=(\w+)&?/.test("?room=any_characters123")
// => true
"?room=any_characters123".match(/room=(\w+)&?/)
// => ["room=any_characters123", "any_characters123"]
Run the string through two regex tests, the one you already have, and then this one:
(?<=room=)(\w){1,}$

match everything between brackets

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.

RegEx - Get All Characters After Last Slash in URL

I'm working with a Google API that returns IDs in the below format, which I've saved as a string. How can I write a Regular Expression in javascript to trim the string to only the characters after the last slash in the URL.
var id = 'http://www.google.com/m8/feeds/contacts/myemail%40gmail.com/base/nabb80191e23b7d9'
Don't write a regex! This is trivial to do with string functions instead:
var final = id.substr(id.lastIndexOf('/') + 1);
It's even easier if you know that the final part will always be 16 characters:
var final = id.substr(-16);
A slightly different regex approach:
var afterSlashChars = id.match(/\/([^\/]+)\/?$/)[1];
Breaking down this regex:
\/ match a slash
( start of a captured group within the match
[^\/] match a non-slash character
+ match one of more of the non-slash characters
) end of the captured group
\/? allow one optional / at the end of the string
$ match to the end of the string
The [1] then retrieves the first captured group within the match
Working snippet:
var id = 'http://www.google.com/m8/feeds/contacts/myemail%40gmail.com/base/nabb80191e23b7d9';
var afterSlashChars = id.match(/\/([^\/]+)\/?$/)[1];
// display result
document.write(afterSlashChars);
Just in case someone else comes across this thread and is looking for a simple JS solution:
id.split('/').pop(-1)
this is easy to understand (?!.*/).+
let me explain:
first, lets match everything that has a slash at the end, ok?
that's the part we don't want
.*/ matches everything until the last slash
then, we make a "Negative lookahead" (?!) to say "I don't want this, discard it"
(?!.*) this is "Negative lookahead"
Now we can happily take whatever is next to what we don't want with this
.+
YOU MAY NEED TO ESCAPE THE / SO IT BECOMES:
(?!.*\/).+
this regexp: [^\/]+$ - works like a champ:
var id = ".../base/nabb80191e23b7d9"
result = id.match(/[^\/]+$/)[0];
// results -> "nabb80191e23b7d9"
This should work:
last = id.match(/\/([^/]*)$/)[1];
//=> nabb80191e23b7d9
Don't know JS, using others examples (and a guess) -
id = id.match(/[^\/]*$/); // [0] optional ?
Why not use replace?
"http://google.com/aaa".replace(/(.*\/)*/,"")
yields "aaa"

Regular Expression - followed by

How can I write a regex that match this
123/456
123/456/?
but not this
123/456/
I want on the second / it must be followed by a ?.
For Example I would like it to match this
'123/456'.match(X) // return ['123/456']
'123/456/?'.match(X) // return ['123/456/?']
'123/456/'.match(X) // return null
Update
I missed to say one important thing. It must not end with '?', a string like '123/456/?hi' should also match
You can try this regex: \d{3}/\d{3}(/\?.*)?
It will match
3 digits
followed by a /
followed by 3 digits
followed by /?any_text (e.g. /?hi) (optional)
This example uses regular expression anchors like ^ and $, but they are not required if you only try to match against the target string.
var result = '123/456/?hi'.match(/\d{3}\/\d{3}(\/\?.*)?/);
if (result) {
document.write(result[0]);
}
else {
document.write('no match');
}
This regular expression will work /^\d{3}\/\d{3}(\/\?.*)?/
See this JSFiddle.
Note: if you think it should match any number of digits then use \d+ instead of \d{3}. The later matches exactly 3 digits.
Here you are:
[0-9]+/[0-9]+(/\?[^ ]*)?
What other rules do you have?
If you want to accept all strings with last character other than ?, use "[^?]$"
If you want to accept strings that start with 123/456 and optionally end with /?, use "^123/456(/\?)?$"
I think this should work:
'123/456'.match(/^123\/456(\/\?)?$/) // returns ["123/456", undefined]
'123/456/'.match(/^123\/456(\/\?)?$/) // returns null
'123/456/?'.match(/^123\/456(\/\?)?$/) // returns ["123/456/?", "/?"]
EDIT: added the other cases

Categories