There is a string with numbers I need to validate with PHP preg_match.
If it starts with 10 or 20 or 30, I need 7 more numbers after the inital 2, but in any other cases I need 8 numbers only and don't care what are the lead characters.
The first part is the simple one
/^(1|2|3)0\d{7}$
But how can I add an ELSE part? There I need a simple
^\d{8}$
I need to match these examples:
101234567
201234567
12345678
33445566
You may use
^(?:[1-3]0\d{7}|(?![1-3]0)\d{8})$
See the regex demo
Details
^ - start of string
(?: - start of a non-capturing group:
[1-3]0\d{7} - 1, 2 or 3, then 0 and any 7 digits
| - or
(?![1-3]0)\d{8} - no 10, 20 or 30 immediately at the start of the string are allowed, then any 8 digits are matched
) - end of the group
$ - end of the string.
Here's an alternative using (?(?=regex)then|else) aka conditionals:
^(?(?=[1-3]0)[1-3]0\d{7}|\d{8})$
It literally says: if [1-3]0 is right at the start, match [1-3]0\d{7}, else match \d{8}.
Demo: https://regex101.com/r/LXoHyk/1 (examples shamelessly taken from Wiktor's answer)
Related
Thanks to anyone that will try to help me.
I struggle into making a regex that can do this case :
I want every match of "Heure Pleine Saison Basse" that occur after the first occurence of "Acheminement conso".
Using the raw text below, i want to match "Heure Pleine Saison Basse" 3 5 6 7 and not 1 & 2.
Do not use the number inside characted recognition, it is just here to help you uderstand which chain i want to match
This example regex only match the last occurrence :
Acheminement[\s\S]*(Heure Pleine Saison Basse)
Here is a great raw text example :
Electricité n° de\n
compteur ancien\n
index nouvel\n
index conso\n
kWh/Qté prix unitaire\n
HT en euros montant HT\n
en euros taux de\n
TVA\n
Contribution cee du 14/07/22 au 13/08/22 143020,00495 70,7920,0%\n
Evolutions arenh du 14/07/22 au 13/08/22 14302-0,03149 -450,3720,0%\n
Consommation du 14/07/22 au 13/08/22 154\n
Heure Pleine Saison Basse 1
Heure Pleine Saison Basse 2
Heure Creuse Saison Basse 2
Acheminement conso\n
kWh/Qté prix unitaire\n
HT en euros montant HT\n
en euros taux de\n
TVA\n
Composante de comptage du 1
Composante de comptage du 2
Composante de soutirage du 1
Composante de soutirage du 2
Composante de gestion 1
Composante de gestion 2
Consommation du 14/07/22 au 31/07/22 Heure Pleine Saison Basse 56200,02000 112,4020,0%\n
Heure Creuse Saison Basse 26840,01700 45,6320,0%\n
Consommation du 01/08/22 au 13/08/22\n
Heure Pleine Saison Basse 3
Heure Creuse Saison Basse 4
Heure Pleine Saison Basse 5
Heure Pleine Saison Basse 6
Heure Pleine Saison Basse 7
Services et prestations techniques conso\n
kWh/Qté prix unitaire\n
HT en euros montant HT\n
en euros taux de\n
TVA\n
Espace Client Gratuit\n
Taxes et Contributions conso\n
You can use
'/(?:\G(?!\A)|Acheminement conso)[\s\S]*?\KHeure Pleine Saison Basse/u'
'/(?:\G(?!\A)|Acheminement conso).*?\KHeure Pleine Saison Basse/su'
See the regex demo. Details:
(?:\G(?!\A)|Acheminement conso) - either Acheminement conso or the end of the previous match (\G(?!\A) is matching what \G operator matches except the position at the start of string that is "cancelled" with the (?!\A) negative lookahead)
[\s\S]*? - any zero or more chars as few as possible
\K - omit the text matched so far
Heure Pleine Saison Basse - a fixed string.
The u flag is necessary when you have to deal with Unicode strings.
The s flag is useful to make . match any characters including line breaks.
i can't figure out this thing i think it possible with only one pattern, please help me improve.
I have this string 2 / 3 items and i wont receive only 2 / 3
Items can also be write in cirillic so 2 / 3 штуки
So i think the best way is use \D all non digit (result 23)
But this delete also the slash that i want to keep, how i can do?
// this was my solution for now,
// but it not complete for cirillic cause i have an error
// it return: 2 / 3 �
// maybe is something with encoding?
preg_replace('#[a-zA-Zа-яА-Я]*#', '', '2 / 3 штуки');
// so i chose to do this, but doesn't know how to keep slash
preg_replace('#[\D]*#', '', '2 / 3 штуки');
// it return: 23
# How to get 2 / 3 ?
You can use
if (preg_match('~\d+\s*/\s*\d+~u', $text, $match)) {
echo $match[0];
}
Also, if the fraction part is optional, use
preg_match('~\d+(?:\s*/\s*\d+)?~u', $text, $match)
And if you need to extract all occurrences, use preg_match_all:
preg_match_all('~\d+(?:\s*/\s*\d+)?~u', $text, $matches)
See the regex demo and the PHP demo. Note that preg_match extracts the match rather than remove it (as is the case with preg_replace).
Pattern details
\d+ - one or more digits
- \s*/\s* - / enclosed with zero or more whitespaces
\d+ - one or more digits
Note that u is used in case the whitespace in your string can be other than regular ASCII whitespace, like \xA0.
I have these two regular expression
^(((98)|(\+98)|(0098)|0)(9){1}[0-9]{9})+$
^(9){1}[0-9]{9}+$
How can I combine these phrases together?
valid phone :
just start with : 0098 , +98 , 98 , 09 and 9
sample :
00989151855454
+989151855454
989151855454
09151855454
9151855454
You haven't provided what passes and what doesn't, but I think this will work if I understand correctly...
/^\+?0{0,2}98?/
Live demo
^ Matches the start of the string
\+? Matches 0 or 1 plus symbols (the backslash is to escape)
0{0,2} Matches between 0 and 2 (0, 1, and 2) of the 0 character
9 Matches a literal 9
8? Matches 0 or 1 of the literal 8 characters
Looking at your second regex, it looks like you want to make the first part ((98)|(\+98)|(0098)|0) in your first regex optional. Just make it optional by putting ? after it and it will allow the numbers allowed by second regex. Change this,
^(((98)|(\+98)|(0098)|0)(9){1}[0-9]{9})+$
to,
^(?:98|\+98|0098|0)?9[0-9]{9}$
^ this makes the non-grouping pattern optional which contains various alternations you want to allow.
I've made few more corrections in the regex. Use of {1} is redundant as that's the default behavior of a character, with or without it. and you don't need to unnecessarily group regex unless you need the groups. And I've removed the outer most parenthesis and + after it as that is not needed.
Demo
This regex
^(?:98|\+98|0098|0)?9[0-9]{9}$
matches
00989151855454
+989151855454
989151855454
09151855454
9151855454
Demo: https://regex101.com/r/VFc4pK/1/
However note that you are requiring to have a 9 as first digit after the country code or 0.
I need some help with writing regexp to parse input strings like this ones:
test-12-1
blabla12412-5
t-dsf-gsdg-x-10
to next matches:
test and 1
blabla12412 and 5
t-dsf-gsdg-x and 10
I try to reach it by using something like
$matches = [];
preg_match('/^[a-zA-Z0-9]+(-\d+)+$/', 'test-12-1', $matches);
But I received unexpected result:
array (
0 => 'test-12-1',
1 => '-1',
)
You can move forward with help on this playground: https://ru.functions-online.com/preg_match.html?command={"pattern":"/^[a-zA-Z0-9]+(-\d+)+$/","subject":"test-12-1"}
Thanks a lot!
You may use
'~^(.*?)(?:-(\d+))+$~'
See the regex demo
Details
^ - start of string
(.*?) - Group 1: any zero or more chars other than line break chars, as few as possible
(?:-(\d+))+ - 1 or more occurrences of
- - a hyphen
(\d+) - Group 2: one or more digits (the last occurrence is kept in the group value since it is located in a repeated non-capturing group)
$ - end of string.
So I know it would be easier to just use the php is_numeric function, but what i'm trying to do is create a regular expression, mostly for learning regex, to test test scores. The range can be 0-100, but can have 2 decimal places. This is what I have so far and its not working.
if (preg_match("^([0-9]){2,3})(.[0-9]{2})?$([0-9]{1})?$", $quiz1))
{
echo "match";
}
else {
$error = true;
}
If I'm thinking correctly the literal meaning:
start of string find characters 0-9, for two places.
optional end of string decimal and find characters 0-9, for two places.
optional end of string find characters 0-9, for 1 place.
Why not something like this?
/^(?:100|\d{1,2})(?:\.\d{1,2})?$/
^ - beginning of string
(?:100|\d{1,2}) - non-capturing group, 100 or 0-99
(?:.\d{1,2})? - optional non-capturing group (.# or .##)
$ - end of string
Results:
php > $tests = array(0, 5, 10, 50, 100, 99.5, 75.43, 75.436, 101);
php > foreach ($tests as $test) { print $test . " - " . preg_match("/^(?:100|\d{1,2})(?:\.\d{1,2})?$/", $test) . "\n"; }
0 - 1
5 - 1
10 - 1
50 - 1
100 - 1
99.5 - 1
75.43 - 1
75.436 - 0
101 - 0
75F43 - 0
Yours doesn't work even when I add the slashes and remove the extra ).
php > foreach ($tests as $test) { print $test . " - " .
preg_match("/^([0-9]{2,3})(.[0-9]{2})?$([0-9]{1})?$/", $test) . "\n"; }
0 - 0
5 - 0
10 - 1
50 - 1
100 - 1
99.5 - 0
75.43 - 1
75.436 - 0
101 - 1
75F43 - 1
Surround your expression with / characters
http://php.net/manual/en/regexp.reference.delimiters.php
gpojd's answer is correct. However, here's why your regex isn't working.
First of all, you want the first $ inside the ()'s. Because otherwise it will need to match the end of the string, and then later after that the end of the string again, which is of course impossible.
Second, the dot character needs to become \. because a dot by itself matches any character, but you want an actual dot. Lastly, you need delimiters, like someone else suggested. Here's what your regex matches:
first, two or three digits, mandatory.
Then, any character followed by two digits, optionally.
Then, the end of the string, mandatory.
Then, one digit, optionally.
Then, the end of the string again, mandatory.
Since you're a programmer, it can be hard to get used to the way of thinking with regular expressions; you're used to thinking in terms of if-else statements but regular expressions don't really work that way.
Again, the option above is good enough but if I were to write a regex for this I'd put:
/^100(.00)?|([1-9]?[0-9])(\.[0-9]{2})?$/
So, either 100 followed by an optional .00, or: first, an optional nonzero digit and then a mandatory digit (those make the numbers 0 to 99), then optionally a dot followed by two digits.