PHP preg_match regular expression for find date in string - php

I try to make system that can detect date in some string, here is the code :
$string = "02/04/16 10:08:42";
$pattern = "/\<(0?[1-9]|[12][0-9]|3[01])\/\.- \/\.- \d{2}\>/";
$found = preg_match($pattern, $string);
if ($found) {
echo ('The pattern matches the string');
} else {
echo ('No match');
}
The result i found is "No Match", i don't think that i used correct regex for the pattern. Can somebody tell me what i must to do to fix this code

First of all, remove all gibberish from the pattern. This is the part you'll need to work on:
(/0?[1-9]|[12][0-9]|3[01]/)
(As you said, you need the date only, not the datetime).
The main problem with the pattern, that you are using the logical OR operators (|) at the delimiters. If the delimiters are slashes, then you need to replace the tube characters with escaped slashes (/). Note that you need to escape them, because the parser will not take them as control characters. Like this: \/.
Now, you need to solve some logical tasks here, to match the numbers correctly and you're good to go.
(I'm not gonna solve the homework for you :) )
These articles will help you to solve the problem tough:
Character classes
Repetition opetors
Special characters
Pipe character (alternation operator)
Good luck!

In your comment you say you are looking for yyyy, but the example says yy.
I made a code for yy because that is what you gave us, you can easily change the 2 to a 4 and it's for yyyy.
preg_match("/((0|1|2|3)[0-9])\/\d{2}\/\d{2}/", $string, $output_array);
Echo $output_array[1]; // date
Edit:
If you use this pattern it will match the time too, thus make it harder to match wrong.
((0|1|2|3)[0-9])/\d{2}/\d{2}\s+\d{2}:\d{2}:\d{2}
http://www.phpliveregex.com/p/fjP
Edit2:
Also, you can skip one line of code.
You first preg_match to $found and then do an if $found.
This works too:
If(preg_match($pattern, $string, $found))}{
Echo $found[1];
}Else{
Echo "nothing found";
}
With pattern and string as refered to above.
As you can see the found variable is in the preg_match as the output, thus if there is a match the if will be true.

Related

Regex fomatting and design for a query

I'm having a some trouble formatting my regular expression for my PHP code using preg_match().
I have a simple string usually looking like this:
"q?=%23asdf".
I want my regular expression to only pass true if the string begins with "q?=%23" and there is a character at the end of the 3. So far one of the problems I have had is that the ? is being pulled up by the regex so doing something like
^q?=23 doesn't work. I am also having problems with contiguous searching in Regex expressions (because I can't figure out how to search after the 3).
So for clarification: "q?=%23asd" should PASS and "q?=%23" should FAIL
I'm no good with Regex so sorry if this seems like a beginner question and thanks in advance.
Just use a lookahead to check whether the character following 3 is an alphabet or not,
^q\?=%23(?=[a-zA-Z])
Add . instead of [A-Za-z] only if you want to check for any character following 3,
^q\?=%23(?=.)
Code would be,
$theregex = '~^q\?=%23(?=[a-z])~i';
if (preg_match($theregex, $yourstring)) {
// Yes! It matches!
}
else { // nah, no luck...
}
So the requirement is: Start with q?=%23, followed by at least one [a-z], the pattern could look like:
$pattern = '/^q\?=%23[a-z]+/i';
Used i (PCRE_CASELESS) modifier. Also see example at regex101.
$string = "q?=%23asdf";
var_dump(figureOut($string));
function figureOut($string){
if(strpos($string, 'q?=%23') == 0){
if(strlen($string) > 6){
return true;
}else{ return false;}
}
}

regex to clean up url

I am looking for a way to get a valid url out of a string like:
$string = 'http://somesite.com/directory//sites/9/my_forms/3-895a3e/somefilename.jpg|:||:||:||:|19845';
My original solution was:
preg_match('#^[^:|]*#', str_replace('//', '/', $string), $modifiedPath);
But obviously its going to remove a slash from the http:// instead of the one in the middle of the string.
My expected output that I want from the original is:
http://somesite.com/directory/sites/9/my_forms/3-895a3e/somefilename.jpg
I could always break off the http part of the string first but would like a more elegant solution in the form of regex if possible. Thanks.
This will do exactly what you are asking:
<?php
$string = 'http://somesite.com/directory//sites/9/my_forms/3-895a3e/somefilename.jpg|:||:||:||:|19845';
preg_match('/^([^|]+)/', $string, $m); // get everything up to and NOT including the first pipe (|)
$string = $m[1];
$string = preg_replace('/(?<!:)\/\//', '/' ,$string); // replace all occurrences of // as long as they are not preceded by :
echo $string; // outputs: http://somesite.com/directory/sites/9/my_forms/3-895a3e/somefilename.jpg
exit;
?>
EDIT:
(?<!X) in regular expressions is the syntax for what is called a lookbehind. The X is replaced with the character(s) we are testing for.
The following expression would match every instance of double slashes (/):
\/\/
But we need to make sure that the match we are looking for is NOT preceded by the : character so we need to 'lookbehind' our match to see if the : character is there. If it is then we don't want it to be counted as a match:
(?<!:)\/\/
The ! is what says NOT to match in our lookbehind. If we changed it to (?=:)\/\/ then it would only match the double slashes that did have the : preceding them.
Here is a Quick tutorial that can explain it all better than I can lookahead and lookbehind tutorial
Assuming all your strings are in the form given, you don't need any but the simplest of regexes to do this; if you want an elegant solution, then a regex is definitely not what you need. Also, double slashes are legal in a URL, just like in a Unix path, and mean the same thing a single slash does, so you don't really need to get rid of them at all.
Why not just
$url = array_shift(preg_split('/\|/', $string));
?
If you really, really care about getting rid of the double slashes in the URL, then you can follow this with
$url = preg_replace('/([^:])\/\//', '$1/', $url);
or even combine them into
$url = preg_replace('/([^:])\/\//', '$1/', array_shift(preg_split('/\|/', $string)));
although that last form gets a little bit hairy.
Since this is a quite strictly defined situation, I'd consider just one preg to be the most elegant solution.
From the top of my head:
$sanitizedURL = preg_replace('~((?<!:)/(?=/)|\\|.+)~', '', $rawURL);
Basically, what this does is look for any forward slash that IS NOT preceded by a colon (:), and IS followed bij another forward slash. It also searches for any pipe character and any character following it.
Anything found is removed from the result.
I can explain the RegEx in more detail if you like.

preg_replace returns unexpected results to $1

<?php
$data='123
[test=abc]cba[/test]
321';
$test = preg_replace("(\[test=(.+?)\](.+?)\[\/test\])is","$1",$data);
echo $test;
?>
I expect the above code to return
abc
but instead of returning abc it returns
123 abc 321
Please tell me what I am doing wrong.
You're only replacing the matched part (the BBcode section). You're leaving the rest of the string untouched.
If you also want to remove the leading/trailing text, include those in the expression:
$test = preg_replace("(.*\[test=(.+?)\](.+?)\[\/test\].*)is","$1",$data);
I don't know if you're aware of this, but the outermost set of parentheses in your regex does not form a group (capturing or otherwise). PHP is interpreting them as regex delimiters. If you are aware of that, and you're using them as delimiters on purpose, please don't. It's usually best to use a non-bracketing character that never has any special meaning in regexes (~, %, #, etc.).
I agree with Casimir that preg_match() is the tool you should be using, not preg_replace(). But his solution is trickier than it needs to be. Your original regex works fine; all you have to do is grab the contents of the first capturing group, like so:
if (preg_match('%\[test=(.+?)\](.+?)\[/test\]%si', $data, $match)) {
$test = $match[1];
}
You don't need to use a replace here, all that you need is to take something in the string. To do that preg_match is more useful:
$data='123
[test=abc]cba[/test]
321';
$test = preg_match('~\[test=\K[^\]]++~', $data, $match);
echo $match[0];

simple preg_match not returning expected results

I went through a few basics on preg match but its quite difficult when your new to it.
What im trying to do is search for this instance in a string
bug1234
it shouldnt be case sensitive so bug1234 or BuG1234 should work
it must be the word bug followed by any 4 numbers
there should be no spaces or anything in between bug1234 so bug-1234 should not be a match
it should ignore things like bug1234z and abug1234 so it must be bug1234 with nothing prefixing it or coming directly after it unless there is a space between then so "there is a problem with bug1234 that i cant solve" would be a match.
Just to clarify it can be any number not 1234 specifically but they must be 4 digits
Heres my lame attempt:
$file_string = $workdetails->text;
$file_string = strtolower($file_string);
$bugkey = "/bug[0-9]{4}/";
$nosey = preg_match($bugkey, $file_string);
if($nosey !== false)
{
echo "We have a match baby!!"
}
That just seemed to return all sorts, empty string,s string with no mention of the word bug
Try changing the regex to:
/\bbug[0-9]{4}\b/i
The \b modifier will only match on a word boundary so that makes sure it doesn't match things like abug1234, bug12345 or bug1234was bad. I also added the i modifier so it is case insensitive. You no longer need to use strtolower.
Also, preg_match typically returns an integer, and returns (int)0 if there is no match. It only returns FALSE on failure. Therefore you should change the match check to be:
if ($nosey > 0) {
// or just
if ($nosey) {
Try it with:
preg_match('/\b(bug\d{4})/i', $file_string, $match);
print_r($match);
The modifier i stands for case insensitive and the \b is for a whole word only (word boundary).
Try this: /(?ism)bug(?i-sm)[0-9]{4}/
Tested on the Regular Expression Test Tool
With data:
sdfsfsbUG1234cccs
Cheers!

PHP Reverse Preg_match [duplicate]

This question already has answers here:
Regular expression to match a line that doesn't contain a word
(34 answers)
Closed 4 years ago.
if(preg_match("/" . $filter . "/i", $node)) {
echo $node;
}
This code filters a variable to decide whether to display it or not. An example entry for $filter would be "office" or "164(.*)976".
I would like to know whether there is a simple way to say: if $filter does not match in $node. In the form of a regular expression?
So... not an "if(!preg_match" but more of a $filter = "!office" or "!164(.*)976" but one that works?
This can be done if you definitely want to use a "negative regex" instead of simply inverting the result of the positive regex:
if(preg_match("/^(?:(?!" . $filter . ").)*$/i", $node)) {
echo $node;
}
will match a string if it doesn't contain the regex/substring in $filter.
Explanation: (taking office as our example string)
^ # Anchor the match at the start of the string
(?: # Try to match the following:
(?! # (unless it's possible to match
office # the text "office" at this point)
) # (end of negative lookahead),
. # Any character
)* # zero or more times
$ # until the end of the string
The (?!...) negative assertion is what you're looking for.
To exclude a certain string from appearing anywhere in the subject you can use this double assertion method:
preg_match('/(?=^((?!not_this).)+$) (......)/xs', $string);
It allows to specify an arbitrary (......) main regex still. But you could just leave that out, if you only want to forbid a string.
Answer number 2 by mario is the correct answer, and here is why:
First to answer the comment by Justin Morgan,
I'm curious, do you have any idea what the performance of this would
be as opposed to the !preg_match() approach? I'm not in a place where
I can test them both. – Justin Morgan Apr 19 '11 at 21:53
Consider the gate logic for a moment.
When to negate preg_match(): when looking for a match and you want the condition to be 1)true for the absence of the desired regex, or 2)false for the regex being present.
When to use negative assertion on the regex: when looking for a match and you want the condition to be true if the string ONLY matches the regex, and fail if anything else is found. This is necessary if you really need to test for undesireable characters while allowing ommission of permitted characters.
Negating the result of (preg_match() === 1) only tests if the regex is present. If 'bar' is required, and numbers aren't allowed, the following won't work:
if (preg_match('bar', 'foo2bar') === 1) {
echo "found 'bar'"; // but a number is here, so fail.
}
if (!pregmatch('[0-9]', 'foobar') === 1) {
echo "no numbers found"; // but didn't test for 'bar', so fail.
}
So, in order to really test multiple regexes, a beginner would test using multiple preg_match() calls... we know this is a very amateur way to do it.
So, the Op wants to test a string for possible regexes, but the conditional may only pass as true if the string contains at least one of them. For most simple cases, simply negating preg_match() will suffice, but for more complex or extensive regex patterns, it won't. I will use my situation for a more real-life scenario:
Say you want to have a user form for a person's name, particularly a last name. You want your system to accept all letters regardless of case and placement, accept hyphens, accept apostrophes, and exclude all other characters. We know that matching a regex for all undesired characters is the first thing we think of, but imagine you are supporting UTF-8... that's alot of characters! Your program will be nearly as big as the UTF-8 table just on a single line! I don't care what hardware you have, your server application has a finite limit on how long a command be, not to mention the limit of 200 parenthesized subpatterns, so the ENTIRE UTF-8 character table (minus [A-Z],[a-z],-,and ') is too long, never mind that the program itself will be HUGE!
Since we won't use an if (!preg_match('.#\\$\%... this can be quite long and impossible to evaluate... on a string to see if the string is bad, we should instead test the easier way, with an assertion negative lookaround on the regex, then negate the overall result using:
<?php
$string = "O'Reilly-Finlay";
if (preg_match('/?![a-z\'-]/i', $string) === 0) {
echo "the given string matched exclusively for regex pattern";
// should not work on error, since preg_match returns false, which is not an int (we tested for identity, not equality)
} else {
echo "the given string did not match exclusively to the regex pattern";
}
?>
If we only looked for the regex [a-z\'-]/i , all we say is "match string if it contains ANY of those things", so bad characters aren't tested. If we negated at the function, we say "return false if we find a match that contained any of these things". This isn't right either, so we need to say "return false if we match ANYTHING not in the regex", which is done with lookahead. I know the bells are going off in someone's head, and they are thinking wildcard expansion style... no, lookahead doesn't do this, it just does negation on each match, and continues. So, it checks first character for regex, if it matches, it moves on until it finds a non-match or the end. After it finishes, everything that was found to not match the regex is returned to the match array, or simply returns 1. In short, assert negative on regex 'a' is the opposite of matching regex 'b', where 'b' contains EVERYTHING ELSE not matchable by 'a'. Great for when 'b' would be ungodly extensive.
Note: if my regex has an error in it, I apologize... I have been using Lua for the last few months, so I may be mixing my regex rules. Otherwise, the '?!' is proper lookahead syntax for PHP.

Categories