RegEx not matching all required chars. What did I do wrong? - php

I want to allow inputs like _X_C or _X_X_X with the following regex:
^(\_X\_C|\_X\_L|\_L?)((\_X){0,3})$
The following should be allowed only once:
_X_C
_X_L
_L
or ...
_X_X_X (0 to threetimes)
The only thing that does not work is the allowance of "_X_X_X" or even "_X"
What did I do wrong?

You may use
^(?:_X_C|_X_L|_L?|(?:_X){0,3})$
^(?:_X_[CL]|_L?|(?:_X){0,3})$
See the regex demo.
Details:
^ - start of string
(?: - start of a non-capturing group:
_X_[CL]| - _X_ and then C or L, or
_L?| - a _ and then an optional L, or
(?:_X){0,3} - zero, one, two or three occurrences of _X substring
) - end of the group
$ - end of string.

Related

How to apply regular expressions to get a number from a dynamic string

I have a variable that can contain a few variations, it also contains a number which can be any number.
The variations:
($stuksprijs+9.075);
($stuksprijs-9.075);
($stuksprijs*9.075);
($m2+9.075);
($m2-9.075);
($m2*9.075);
($o+9.075);
($o-9.075);
($o*9.075);
These are the only variations except for the numbers in it, they can change. And I need that number.
So there can be:
($m2+5);
or
($o+8.25);
or
($stuksprijs*3);
How can I get the number from those variations? How can I get the 9.075 or 5 or 8.25 or 3 from my above examples with regular expression?
I am trying to fix this with PHP, my variable that contains the string is: $explodeberekening[1]
I read multiple regex tutorials and got it to work for a single string that never changes, but how can I write a regex to get the number from above variations?
As per my comment, which seems to have worked, you can try:
^\(\$(?:stuksprijs|m2|o)[+*-](\d+(?:\.\d+)?)\);$
The number is captured in the 1st capture group. See the online demo.
A quick breakdown:
^ - Start string anchor.
\(\$ - Literally match "($".
(?: - Open a non-capture group to list alternation:
stuksprijs|m2|o - Match one of these literal alternatives.
) - Close non-capture group.
[+*-] - Match one of the symbols from the character-class.
( - Open 1st capture group:
\d+ - 1+ digits.
(?:\.\d+)? - Extra optional non-capture group to match a literal dot and 1+ digits.
) - Close 1st capture group.
\); - Literally match ");".
$ - End string anchor.

Regex allow only datetime (h:m:s) or an integer

I'm looking for a regex pattern that only accept datetime (eg: 01:02:00) or an integer (123456789), The datetime can accept optional leading zero i mean it can also allow 1:2:10
It should allow or disallow these inputs:
0123456789✅
0123456789 word❌
word❌
01:00:10✅
1:2:10✅
1:10❌
1:2:❌
1:❌
I tried this pattern but not working correctly:
if (preg_match('~^[0-9:]*$|[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}~')) {
//allowed
}
https://regex101.com/r/mRxBNu/1
I would just use a regex alternation here:
^(?:\d+|\d{1,2}:\d{1,2}:\d{1,2})$
Demo
Explanation of regex:
^ from the start of the input
(?:
\d+ match one or more digits
| OR
\d{1,2}:\d{1,2}:\d{1,2} match an H:M:S timestamp
)
$ end of the input
I'd suggest the following could work:
^\d\d?(?:\d*|:\d\d?:\d\d?)$
See the online demo
^ - Start string anchor.
\d\d? - A single digit and an optional one.
(?: - Open non-capture group:
\d* - 0+ digits;
| - Or:
:\d\d?:\d\d? - A colon, digit and an optional digit (two times in a row).
) - Close non-capture group.
$ - End string anchor.
This regex will detect any date and a 10 digit Integer/Number
^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^([0-9]{10})$
Inspired from here :
https://ihateregex.io/expr/date/
I just added the last "|([0-9]{10})" for the 10 digit number.

How get for second match group with number?

Text for example
data=1 type=old
data=2 type=test (2)
type=test data=3 (3)
I need get data-id from 2 and 3 lines
My code:
(data=([\d]+)|type=test)\s+(?!\1)((?1))
but don't get data=3
You need the g from global and m from multiline in your regex:
/(data=([\d]+)|type=test)\s+(?!\1)((?1))/gm
In the most simple form you may use
^(?=.*type=test).*data=(\d+)
See the regex demo
You may add word/whitespace boundaries later if necessary, e.g.
^(?=.*\btype=test\b).*\bdata=(\d+)\b
^(?=.*(?<!\S)type=test(?!\S)).*(?<!\S)data=(\d+)(?!\S)
The point is
^ - start of string
(?=.*type=test) - there must be type=test after any 0+ chars as many as possible to the right of the current position
.* - any 0+ chars other than line break chars as many as possible
data= - a string
(\d+) - Group 1: 1+ digits

Creating a regular expression that will match requirements in a string

The issue
I need to write a regular expression that will match the following requirements in a string with the structure {A/B}.
Requirements/Conditions:
A and B can only be exactly one of [UGWRB].
A structure where U or G do not appear is invalid.
A structure where both characters are equal is invalid.
U or G must appear in the combination at least once.
The structure can repeat or continue infinite times, as long as each following instance is still valid when read alone. (see valid matches below)
Valid matches:
{U/G}{U/G}{U/G}
{W/G}{U/B}
{U/G}{U/B}
{U/G}
{G/U}
{U/B}
...
Invalid matches:
{U/U}{U/U}
{U/U}{G/G}
{U/G}{U/U}
{U/G}{R/B}
{G/G}
{R/B}
{W/R}
{B/W}
...
My attempt
This is what I have gotten so far, but out of all the combinations of UGWRB, I'm only getting 8 matches out of 14.
{([UG])(?(1)|\w)\/(?(1)\w|[UG])}
You have to work with lookaheads both negative and positive in order to accomplish the task:
^(?:{(?=[^{}]*[UG])([UGWRB])\/(?!\1)(?1)})+$
See live demo here
Note that m flag should be set.
Regex breakdown:
^ Match start of input string
(?: Start of non-capturing group
{ Match { literally
(?= Start of positive lookahead
[^{}]*[UG] Look for [UG] in combination
) End of lookahead
([UGWRB]) Match and capture a letter from character class
\/(?!\1)(?1) Match / and see if next char is not the same as recently captured one
} Match } literally
)+ End of group, repeat at least once
$ Match end of input string
Try this regex:
^(?!.*{([UGWRB])\/\1})(?:{(?(?=[UG]).\/[UGWRB]|[WRB]\/[UG])})+$
Click for Demo
Explanation:
^ - matches the start of the string
(?!.*{([UGWRB])\/\1}) - negative lookahead to make sure that the structures like {G/G} or {U/U} or {R/R} are not present anywhere in the string
{ - matches {
(?(?=[UG]).\/[UGWRB]|[WRB]\/[UG]) - Regex Conditional. If the current position is followed by either U or G, then the match that character followed by / and the character class [UGWRB]. Otherwise, match the character class [WRB] followed by / followed by U or G
} - matches }
+ - matches 1+ occurrences of the above sub-sequence (?:{(?(?=[UG]).\/[UGWRB]|[WRB]\/[UG])})
$ - matches the end of the string

How can I repeat my pattern with a minor change?

Here is my pattern, \/\d+$. It matches the slash and number which is in the end of string. Now I want to expand it and making it working for a sequence of them.
Here is the input:
ticket/2/1/19
And here is the current result:
ticket/2/1
And this is the expected result:
ticket
How can I do that?
You may wrap \/\d+ with a grouping construct and quantify the group:
(?:\/\d+)+$
See the regex demo
Details
(?: - start of a non-capturing group
\/ - a /
\d+ - 1+ digits
)+ - end of the group, repeated 1 or more times (+)
$ - end of string.

Categories