Correct regex for this pattern - php

I've got some issues understanding this regex.
I tried doing a pattern but does not work like intended.
What I want is [A-Za-z]{2,3}[0-9]{2,30}
That is 2-3 letters in the beginning and 2-30 numbers after that
FA1321321
BFA18098097
I want to use it to validate an input field but can't figure out how the regex should look like.
Can any one that can help me out even explain a bit about it?

Your regex is correct - just make sure to surround it with / in PHP, and perhaps ^, $ if you want it to strictly match the entire string (no extra characters before/after).
$pattern = "/^[A-Za-z]{2,3}[0-9]{2,30}$/"
$found = preg_match($pattern, $your_str);
From the PHP documentation:
preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.

Related

Weird PHP Regex Preg_Match Bug?

My PHP version is PHP 7.2.24-0ubuntu0.18.04.7 (cli). However it looks like this problem occurs with all versions I've tested.
I've encountered a very weird bug when using preg_match. Anyone know a fix?
The first section of code here works, the second one doesn't. But the regex itself is valid. For some reason the something_happened word is causing it to fail.
$one = ' (branch|leaf)';
echo "ONE:\n";
preg_match('/(?:\( ?)?((?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+(?: ?\| ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?: ?\))?/', $one, $matches, PREG_OFFSET_CAPTURE);
print_r($matches); // this works
$two = 'something_happened (branch|leaf)';
echo "\nTWO:\n";
preg_match('/(?:\( ?)?((?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+(?: ?\| ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?: ?\))?/', $two, $matches2, PREG_OFFSET_CAPTURE);
print_r($matches2); // this doesn't work
It seems somehow related to the word something_happened. If I change this word it works.
The regex is matching 2 or more type names separated by | that may or may not be surrounded in (), and each type name may or may not be preceded by any number of [] (or [some number] or [!some number]) and *.
Try it and see for yourself! Please let me know if you know how to fix it!
The problem lies in the (?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+ group: the + quantifier quantifies a group with many subsequent optional patterns, and that creates too many options to match a string before the subsequent patterns.
In PHP, you can workaround the problem by using either
Possessive quantifier:
'/(?:\(\ ?)?((?:(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)++(?:\ ?\|\ ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?:\ ?\))?/'
Note the ++ at the end of the group mentioned.
2. Atomic group:
'/(?:\(\ ?)?((?>(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+(?:\ ?\|\ ?(?:\**\[(?:!?\d+)?\])*\**[A-Za-z_]\w*)+)(?:\ ?\))?/'
See this regex demo. Note the (?>...) syntax.
Also, note how the regex is formatted here, it is very convenient to use the x (extended) flag to break the regex into several lines, format it, so that it could be easier to track down the issue. It is required to escape all literal whitespace and # chars, but it is a minor inconvenience when it comes to debugging long patterns like this.

How to match these strings using preg_match

preg_match('/"\'<>&/', 'misiek"')
Why does not it work ?
As stated in the comments - it does exactly what you told it to do. In your case, you simply check if the string you provide contains the exact substring: "\'<>& anywhere.
So with your pattern, the following strings would result in a match:
"'<>&
LOREM "'<>& IPSUM
Since both of these include the pattern you searched for. However, LO"R'EM<>IPS&UM would not return a match, because you are not checking for the individual characters, only the complete pattern.
If you change your pattern to:
/["\'<>&]/
You instead look for a list of characters. This will return true if any of the characters wrapped in brackets are found.
misiek - would in this case not match
LO"R'EM<>IPS&UM - would match
mis&iek - would match
You can test your regex patterns as well as build them on this site:
https://regex101.com
There you'll also find the available modifiers you can use and how / why to use them.
Good luck!
I am guessing: could it be that you want to match a string containing at least one of the characters listed in your regular expression? In that case you should do the following:
$res=preg_match('/["\'<>&]/' , 'misiek"');
And the result should be positive ($res===1), see here:
http://rextester.com/KYNGYI23753

regular expressions checking two strings

Hi wonder if anyone can help - I'm trying to check for occurance of one of two possible strings using regex - but my knowlege of regex is very limited, so I'm not having much sucess.
I'm trying to look for 'Email' and 'eMailConfirm', this is what I have so far and is working for Email
subject is the id of a input field, so it could be 'name','Email','eMailConfirm'
$subject = $getPromoOuter['label'];
$pattern = '/^Email/';
preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, 0);
I tried a number of potential expressions to try and incorporate the second string but I can't seem to get it to play (plus a few guesswork ones based on others)
any idea how I can concatenate those two strings and check for an occurance of either?
Thanks for looking
I'll just place an answer here, as I do think I have a good idea what your requirement is.
Your current regex is /^Email/ which matches any string which starts with 'Email'. (whether or not it has to start with it is unclear to me).
In case you need to match either Email or eMailConfirm, not at the start of the string, you should go for
/Email|eMailConfirm/
If the matches do need to be at the front of the string, just prepend both with a '^' character:/^Email|^eMailConfirm/

Capturing a pattern of unknown repitition in PCRE

This may be a quick question for experienced regular expressionists, but I'm having trouble getting my match to execute correctly.
Suppose I had a string that looked like this:
http://aaa-bbbb-cc-ddddd-eee-.sub.dom
I would like to go capture all of the "aaa", "bbbb", "cc", and "ddddd" substrings, but I'm not sure how many there will be (e.g., having all triplets up through "zzz").
This is the regular expression I'm trying to use right now:
/http:\/\/(\w*?\-)+\.sub\.dom/
I wrote it this way because:
I want to match substrings, but I want each to terminate when a - is parsed
I want to capture one or more of these substrings
But it seems to only be saving the last match that it makes (in the above case, it would only match "eee-".
Is there a good way to capture all of the matched substrings?
More information: I'm using PHP's PCRE function preg_replace_callback. Thanks!
No, it is not possible to match an unknown number of capture groups.
If you try to repeat a capture group, it will always contain the last value captured.
Could you explain a bit more broadly what you're trying to do? Perhaps there is another simple way to do it (possibly without regular expressions).
If you want the items in the subdomain, and then all matches between the dashes... This should work:
$string = "http://aaa-bbbb-cc-ddddd-eee-.sub.dom";
preg_match("/^http:\/\/([\w-]+?)\..*$/i", $string, $match);
$parts = explode('-', $match[1]);
print_r($parts);
Short of that you will probably have to build a small parsing script to parse the string yourself if that doesn't do it for you.

replace exact match in php

im new to regular expressions in php.
I have some data in which some of the values are stored as zero(0).What i want to do is to replace them with '-'. I dont know which value will get zero as my database table gets updated daily thats why i have to place that replace thing on all the data.
$r_val=preg_replace('/(0)/','-',$r_val);
The code im using is replacing all the zeroes that it finds for eg. it is even replacing zero from 104.67,giving the output 1-4.56 which is wrong. i want that data where value is exact zero that must be replaced by '-' not every zero that it encounter.
Can anyone please help!!
Example of the values that $r_val is having :-
10.31,
391.05,
113393,
15.31,
1000 etc.
This depends alot on how your data is formatted inside $r_val, but a good place to start would be to try:
$r_val = preg_replace('/(?<!\.)\b0\b(?!\.)/', '-', $r_val);
Where \b is a 0-length character representing the start or end of a 'word'.
Strange as it may sound, but the Perl regex documentation is actually really good for explaining the regex part of the preg_* functions, since Perl is where the functionality is actually implemented.
Again, it would be more than helpful if you could supply an example of what the $r_val string really looks like.
Note that \b matches at word boundaries, which would also turn a string like "0.75" into "-.75". Not a desirable result, I guess.
Whilst the other answer does work, it seems overly complex to me. I think you need only to use the ^ and $ chars either side of 0.
$r_val = preg_replace('/^0+$/', '&#45', $r_val);
^ indicates the regex should match from the beginning of the line.
$ indicates the regex should match to the end of the line.
+ means match this pattern 1 or more times
I altered the minus sign to it's html code equivalent too. Paranoid, yes, but we are dealing with numbers after all, so I though throwing a raw minus sign in there might not be the best idea.
Why not just do this?
if ( $r_val == 0 )
$r_val = '-';
You do not need to use a regex for this. In fact, I'd advise against doing so for performance reasons. The operation above is approximately 20x faster than the regex solution.
Also, the PHP manual advises against using regexes for simple replacements:
If you don't need fancy replacing rules (like regular expressions), you should always use this function instead of ereg_replace() or preg_replace().
http://us.php.net/manual/en/function.str-replace.php
Hope that helps!

Categories