Regex negative lookahead to match url - php

I'm trying to match urls
/api/v1/users...
/api/v1/other_stuff...
Except for
/api/v1/users/invitation_register
I've been trying to use negative lookbehind
^\/api.*(?<!\binvitation_register\b)
and several similar constructs and have no idea how to actually do this.
Any help would be more then welcome.

You can use this negative lookahead instead of lookbehind:
^\/api\/(?!v1\/users\/invitation_register\b).*
(?!v1\/users\/invitation_register\b) is a negative lookahead that asserts that v1/users/invitation_register fails after /api/.
RegEx Demo
If your intended match is always starting with /api/v1/... then you can use:
^\/api\/v1\/(?!users\/invitation_register\b).*
which asserts that users/invitation_register fails after /api/va/.

Related

regex skip match if its follows by whitespace and a keyword

Currently trying to match comments with regexes but only if no function follows.
Currently I use a regex which also matches the keyword function.
And then check in the source code (php) if this group is set or not.
/\/\*\*.*?\*\/\s*(function)?/sg
https://regex101.com/r/l0j1ip/1
Now the question is whether it is possible to realize with pure regex.
I have tried it with a simple negative lookahead but without success.
Although the comment is no longer made individually, but then just with the subsequent comment.
/\/\*\*.*?\*\/\s*(?!function)/sg
https://regex101.com/r/PuUUw6/1
Next I tried non capture group. But also there without success.
/(?:\/\*\*.*?\*\/\s*function)|\/\*\*.*?\*\/\s*/sg
https://regex101.com/r/wkQE7E/1
After a comment with the information (*SKIP)(*FAIL) I also tried it without success.
All matches above this keyword are skipped. Also the single matches are skipped.
/\/\*\*.*?\*\/\s*function(*SKIP)(*FAIL)|\/\*\*.*?\*\//sg
https://regex101.com/r/OJSFrF/1
After reading the question again, it should be doable using negative lookahead ; the repetition must be inside the negative expression:
/\/\*\*((?!\*\/).)*\*\/(?!\s*function)/sg
Seems you need to understand better how backtracking works, using .*? instead of .* means the regex engine will try first to match everything after before .* however the negative lookahead makes the match fail and .* continues to match. Using ((?!\*\/).)* can't match \*\/ wheras .*? can, after backtracking.
Another solution is to use atomic group (?>\/\*\*.*?\*\/)(?!\s*function).
Another option without the /s flag could be
/\*\*(?:[^*]*+|\*(?!/)[^*]*+)*\*/(?!\s*function)
The pattern matches:
/\*\* Match /**
(?: Non capture group
[^*]*+ Match any char except * using a possessive quantifier
| Or
\*(?!/) Match * not followed by /
[^*]*+ Match any char except * using a possessive quantifier
)* Close non capture group and optionally repeat
\*/ Match */
(?!\s*function) Negative lookahead, assert not optional whitspace chars followed by function to the right
Regex demo
Note that you don't have to escape the backslash when using a different delimiter.
$regex = '~/\*\*(?:[^*]*+|\*(?!/)[^*]*+)*\*/(?!\s*function)~';

PHP regex - match everything but not exactly one or more word

I try to find any string it not exactly one or more word
My pattern
(?!(^ignoreme$)|(^ignoreme2$))
Iam looking for
ignoreme - no
ignoreme2 - no
ignoremex - match
ignorem - match
gnoreme - match
ignoreme22 - match
But it return many space. How to do that thank.
https://regex101.com/r/u4EsNv/1
You may use this corrected regex:
^(?!ignoreme2?$).*$
Updated RegEx Demo
RegEx Details:
^: Start
(?!ignoreme2?$): Negartive lookahead to fail the match when we have ignoreme or ignoreme2 ahead till end.
.*: Match 0 more of any characters
$: End
Note that regex (?!(^ignoreme$)|(^ignoreme2$)) matches first 2 invalid cases because you have included ^ in negative lookahead expressions not outside. This causes regex engine to start matching after 1st character to satisfy lookahead assertions. (You can see that in regex101 highlighted matches)

Regex Nested Shortcode Does Not Work

Can someone tell me why this does not work ? - https://regex101.com/r/hJ5zN6/11
Test string:
[test][dzspgb_container][dzspgb_row][dzspgb_row_part part="1.4"][dzspgb_element text="whwaha" type_element="text"][/dzspgb_element][dzspgb_element text="test" type_element="text"][/dzspgb_element][/dzspgb_row_part][dzspgb_row_part part="1.4"][/dzspgb_row_part][dzspgb_row_part part="1.4"][/dzspgb_row_part][dzspgb_row_part part="1.4"][/dzspgb_row_part][/dzspgb_row][dzspgb_container]test second[/dzspgb_container][/dzspgb_container][/thisbreaks]
Test regex:
*\[dzspgb_container(.*?)](.*?)\[\/dzspgb_container\](?!\s*\[\/)*
If we remove [/thisbreaks] from the string, it will work.
It's because of the negative lookahead assertion at the end. I suggest you to remove that lookahead and use a greedy regex pattern like below.
\[dzspgb_container(.*?)](.*)\[\/dzspgb_container\]
DEMO
(?!\s*\[\/) asserts that the match won't be followed by (zero or more space characters and a [ symbol)

Lookahead, lookbehind condition in regular expression

The following example is about using lookahead assertion as a condition. I found it in the PHP manual at: http://www.php.net/manual/en/regexp.reference.conditional.php
(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
Here's the description about this regex:
The condition is a positive lookahead assertion that matches an optional sequence of non-letters followed by a letter. In other words, it tests for the presence of at least one letter in the subject. If a letter is found, the subject is matched against the first alternative; otherwise it is matched against the second. This pattern matches strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.
Could anyone tell me why we use lookahead assertion as the condition in this example? Why don't we use lookbehind assertion? I get confused when they're used as conditions like this because I don't know how do they match the subject string. Thanks in advance!
In this case we're using a lookahead assertion to decide which regex to use. It looks like it's deciding between matching dates of the form 01-Jan-12 and 01-01-12. The lookahead assertion sees if there are any letters within what we're trying to match and if so uses the \d{2}-[a-z]{3}-\d{2} to try and match 01-Jan-12 if not it uses \d{2}-\d{2}-\d{2} to try and match 01-01-12.

RegEx - Positive Lookbehind Problem

How do I use a positive look-behind to match more than 1 occurrence using a greedy + ?
This works:
(?<=\w)\w+
But I need to match all \w similar to:
(?<=\w+)\w+
The syntax is wrong in the second example and it does not work.
How do I make a positive lookbehind match multiple occurrences?
A very dirty way to do it is to reverse the string and use a positive lookahead instead. This is a trick that I use in Javascript (no lookbehinds supported there :( ).
So you must do something like:
$string = 'This is a long string that must show this is what will happen';
$str_rev = strrev($string);
if (preg_match('!(si)(?=\w+)(\w+)!i', $str_rev, $matches)) {
print_r($matches);
}
The code above will match is in the occurrences of THIS in the string. The second \w+ is just to show where it matched and is not needed in your example.
Keep in mind that this technique is possible only if you use only one direction for greediness for the Lookbehind/aheads (e.g. you can't use a lookbehind with \w+ together with a lookahead with \w+ )
You probably just want to match it without any lookbehinds and then use your capturing groups:
if (preg_match('~[abc]+([cde]+)~', $string, $matches)) {
echo $matches[1]; // will contain the [cde]+ part
}
Sorry to say, but no quantifiers in lookbehinds!
I found this in the perlretut
Lookahead (?=regexp) can match
arbitrary regexps, but lookbehind
(?<=fixed-regexp) only works for
regexps of fixed width
I assume that this is also valid for the php regex engine.

Categories