My test string:
/custom-heads/food-drinks/51374-easter-bunny-cake
I am trying to capture the number in the string. The constants in that string are the the number is always preceded by 3 /'s and followed by a -.
I am a regex noob and am struggling with this. I cobbled together (\/)(.*?)(-) and then figured I could get the last one programmatically, but I would really like to understand regex better and would love if someone could show me the regex to get the last occurrence of numbers between / and -.
Don't use regexes if possible, i reccomend you to read - https://blog.codinghorror.com/regular-expressions-now-you-have-two-problems/ blog post
To your question, its easier, faster, more bullet proof to get it using splits
const articleName = "/custom-heads/food-drinks/51374-easter-bunny-cake".split("/")[3]
// '51374-easter-bunny-cake'
const articleId = articleName.split("-")[0]
// '51374'
hope it helps
You may use this regex with a capture group:
^(?:[^\/]*\/){3}([^-]+)
Or in modern browsers you can use lookbehind assertion:
/(?<=^(?:[^\/]*\/){3})[^-]+/
RegEx Demo 1
RegEx Demo 2
RegEx Code:
^: Start
(?:[^\/]*\/){3}: Match 0 or more non-/ characters followed by a /. Repeat this group 3 times
([^-]+): Match 1+ of non-hyphen characters
Code:
const s = `/custom-heads/food-drinks/51374-easter-bunny-cake`;
const re = /^(?:[^\/]*\/){3}([^-]+)/;
console.log (s.match(re)[1]);
Use
const str = `/custom-heads/food-drinks/51374-easter-bunny-cake`
const p = /(?:\/[^\/]*){2}\/(\d+)-/
console.log(str.match(p)?.[1])
See regex proof.
EXPLANATION
Non-capturing group (?:\/[^\/]*){2}
{2} matches the previous token exactly 2 times
\/ matches the character / with index 4710 (2F16 or 578) literally (case sensitive)
Match a single character not present in the list below [^\/]
* matches the previous token between zero and unlimited times, as many times as possible, giving back as needed (greedy)
\/ matches the character / with index 4710 (2F16 or 578) literally (case sensitive)
\/ matches the character / with index 4710 (2F16 or 578) literally (case sensitive)
1st Capturing Group (\d+)
\d matches a digit (equivalent to [0-9])
+ matches the previous token between one and unlimited times, as many times as possible, giving back as needed (greedy)
- matches the character - with index 4510 (2D16 or 558) literally (case sensitive)
I would like to extract mkghj.bmg and pp.kp from the following string using a regex used in javascript
avb#gh.lk mkghj.bmg ,,,,fsdsdf.fdfd pllk.kp sdfsdf.bb,,,, pp.kp
Everything enclosed within ,,,, needs to be ignored. There could be multiple instances of ,,,, But they will always occur even number of times (non occurrence is also a possibility) in the string.
Also, avb#gh.lk has an # sign, therefore it needs to be ignored
I guess the rule I am looking for is this - if there is a dot (.) look ahead and look behind :-
If the dot is enclosed inside ,,,, then ignore it
If the dot has an # before it with no space between the dot and #, ignore it
In all other cases, capture an unbroken set of characters (until a space is encountered) on either side of the dot
I came up with this regex, but it is not helpful
[^\, ]+([^# \,]+\w+)[^\, ]+
Generally speaking that is (mind the capturing group):
not_this | neither_this_nor_this | (but_this_interesting_stuff)
For your specific example, this could be
,,,,.*?,,,,|\S+#\S+|(\S+)
You need to check for the existance of group 1, see a demo on regex101.com.
In JS this would be:
var myString = "avb#gh.lk mkghj.bmg ,,,,fsdsdf.fdfd pllk.kp sdfsdf.bb,,,, pp.kp";
var myRegexp = /,,,,.*?,,,,|\S+#\S+|(\S+)/g;
match = myRegexp.exec(myString);
while (match != null) {
if (typeof(match[1]) != 'undefined') {
console.log(match[1]);
}
match = myRegexp.exec(myString);
}
Regex
^[^ ]+ ([^ ]+) ,,,,.*,,,,\s+(.*)
Description
^ asserts position at start of a line
Match a single character not present in the list below [^ ]+
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
matches the character literally (case sensitive)
matches the character literally (case sensitive)
1st Capturing Group ([^ ]+)
Match a single character not present in the list below [^ ]+
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
matches the character literally (case sensitive)
,,,, matches the characters ,,,, literally (case sensitive)
.* matches any character (except for line terminators)
* Quantifier — Matches between zero and unlimited times, as many times as possible, giving back as needed (greedy)
,,,, matches the characters ,,,, literally (case sensitive)
\s+ matches any whitespace character (equal to [\r\n\t\f\v ])
+ Quantifier — Matches between one and unlimited times, as many times as possible, giving back as needed (greedy)
2nd Capturing Group (.*)
.* matches any character (except for line terminators)
You can replace the string between ,,, by '' and than from remaining you can split and search for # sign and filter.
let str = `avb#gh.lk mkghj.bmg ,,,,fsdsdf.fdfd pllk.kp sdfsdf.bb,,,, pp.kp`
let op = str.replace(/,,,.*?,,,,|/g,'').split(' ').filter(e=> !e.includes('#') && e );
console.log(op)
I am parsing strings for tokens that have 2 types of delimiter (similar to mustache templates).
I need a pure reg ex solution that matches {{bob}} in this is {{bob}} a double token. But does NOT match in this is {{{bob}}} a triple token
I am matching the double with
\{\{[^\{]([\s\S]+?)[^\}]\}\}
However, it matches the {{bob}} within the triple {{{bob}}}.
Without the negative look behind i'm struggling to find a pure regex solution. Any pointers?
You could search any whitespace char outside the brackets, something like this:
\s(\{\{([^\{\}]+?)\}\})\s
RegEx:
^(\}?)\{\{[^\{]([\s\S]+?)[^\}]\}\}
Auto Generated Explanation:
^ asserts position at start of the string
1st Capturing Group (\}?)
\}? matches the character } literally (case sensitive)
? Quantifier — Matches between zero and one times, as many times as possible, giving back as needed (greedy)
\{ matches the character { literally (case sensitive)
\{ matches the character { literally (case sensitive)
Match a single character not present in the list below [^\{]
\{ matches the character { literally (case sensitive)
2nd Capturing Group ([\s\S]+?)
Match a single character present in the list below [\s\S]+?
+? Quantifier — Matches between one and unlimited times, as few times as possible, expanding as needed (lazy)
\s matches any whitespace character (equal to [\r\n\t\f\v ])
\S matches any non-whitespace character (equal to [^\r\n\t\f ])
Match a single character not present in the list below [^\}]
\} matches the character } literally (case sensitive)
\} matches the character } literally (case sensitive)
\} matches the character } literally (case sensitive)
Global pattern flags
g modifier: global. All matches (don't return after first match)
You may use the following to extract the matches:
var s = "this is {{{ bad bob triple}}} a triple token {{bob double}} {{bob}} a double token {{{bad token}} {{bad token}}}";
var rx = /(?:^|[^{]){{([^{}]*)}}(?!})/g;
var m, res=[];
while(m=rx.exec(s)) {
res.push(m[1]);
}
console.log(res);
See the regex demo here.
(?:^|[^{]) - either start of string or any char but {
{{ - double {
([^{}]*) - Group 1: any char but { and } zero or more times
}} - double }
(?!}) - not followed immediately with }.
so far I have this regex $fileregex = /([a-z]:\\\\([^\\\\^\\.])*)|(\/[^\/.])/i; but I am very confused on what to do next.
I want to match strings in this format
c:\\something\\else\\something
c:\\something\\else\\something.whatever
/etc/whatever/something/here
/etc/here.txt
/
c:\\
But I don't want to match, for example
c:\oneslash\text.txt
\etc\hi
I am really stuck on my regex especially on repeating the optional path, as one could just request the root.Can anyone help me out with the regex?
This one should work:
preg_match_all('%[A-Za-z]:\\\\\\\\(.*?\\\\\\\\)*.*|/(.*?/)*.*%m', $input, $regs, PREG_PATTERN_ORDER);
for ($i = 0; $i < count($regs[0]); $i++) {
# Matched text = $regs[0][$i];
}
Result:
Description of the Regex:
Match either the regular expression below (attempting the next alternative only if this one fails)
[A-Za-z] Match a single character present in the list below
A character in the range between “A” and “Z”
A character in the range between “a” and “z”
: Match the character “:” literally
\\\\ Match the character “\” literally
\\\\ Match the character “\” literally
( Match the regular expression below and capture its match into backreference number 1
. Match any single character that is not a line break character
*? Between zero and unlimited times, as few times as possible, expanding as needed (lazy)
\\\\ Match the character “\” literally
\\\\ Match the character “\” literally
)* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
. Match any single character that is not a line break character
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
| Or match regular expression number 2 below (the entire match attempt fails if this one fails to match)
/ Match the character “/” literally
( Match the regular expression below and capture its match into backreference number 2
. Match any single character that is not a line break character
*? Between zero and unlimited times, as few times as possible, expanding as needed (lazy)
/ Match the character “/” literally
)* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
. Match any single character that is not a line break character
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
Have you try this:
/^([a-zA-Z]\:|\\\\[^\/\\:*?"<>|]+\\[^\/\\:*?"<>|]+)(\\[^\/\\:*?"<>|]+)+(\.[^\/\\:*?"<>|]+)$/
This regular expression will match any valid file path. It checks local drives and network path. The file extension is required.
Further references : The regular expression library
I'm trying to write a regular expression that takes any word between these two sets of characters:3D and &sa
examples:
3DEvb31p5vFs4_&sa : the output : Evb31p5vFs4_
3D_Ve8_LBztG50_&sa : the output : _Ve8_LBztG50_
I have used the expression: /\w[3D][A-Za-z0-9_-].*sa/g
So the next step is to skip the "3D" and "&sa"
Thanks in advance!
You can use match() with regex /3D(.*)&sa/
var a='3DEvb31p5vFs4_&sa';
var b='3D_Ve8_LBztG50_&sa' ;
document.write(a.match(/3D(.*)&sa/)[1] +'<br>');
document.write(b.match(/3D(.*)&sa/)[1]);
Explanation:
3D(.*)&sa
Debuggex Demo
Try this:
3D(?s)(.*)&sa
Explaination:
3D matches the characters 3D literally (case sensitive)
(?s) Match the remainder of the pattern with the following options:
s modifier: single line. Dot matches newline characters
1st Capturing group (.*)
.* matches any character
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
&sa matches the characters &sa literally (case sensitive)
g modifier: global. All matches (don't return on first match)