regex to get date yyyy-mm-dd from any string - php

first of all excuse me for not being regex familiar that much.What I Would like is a regex that will extract a date like mysql date from any type of string.
Until now I was using this : ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$
However now I want to extract date patterns from other strings and datetime strings I tried altering the regex to ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]). based on some online regex testers, but it fails. Also some times it gave me a result with a 3 digit day.
In other words sting starts with, yyyy-mm-dd and is followed up by spaces characters numbers or anything. How do I extract the date?
UPDATE
I'm testing regex with preg_match here: http://www.pagecolumn.com/tool/pregtest.htm
so far the only thing that seems to work is
[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])

If your string has more than one date form value occurrence and you wanna capture all of them you should use preg_match_all function and if it's not preg_match is enough. Also using ^ and $ means input string is should be just a date, so avoid it.
<?php
$input_string = "yes today is 2013-10-24";
if(preg_match("/\d{4}-\d{2}-\d{2}/", $input_string, $match))
{
print_r($match);
}
else
echo "not matched";
////////////////////////
/* Output:
Array
(
[0] => 2013-10-24
)
*/
Live demo

Try this:
you can use preg_match() or preg_match_all()
$dateArray = preg_match("/(\d{4}-\d{2}-\d{2})/", $str, $match);
Then use strtotime and date
$date = date('Y-m-d',strtotime($match[0]));

To match dates wherever they appear, remove the $ and ^ anchors from your original regex.
To match dates at the start of any input remove the $ at the end (leave the ^).
You can also put the remaining pattern inside parentheses for convenience, so that the match is also captured as a whole.
Your suggested improvement has a spurious dot at the end which will match any character; that was the reason for returning matches with three-digit days.

Just replace ^ for \b.
\b(\d{4}-\d{2}-\d{2})

It is dot in the end of your regexp (it matches any character, except for line breaks)
Try removing it
^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])

Related

How do I match this pattern using preg_match in PHP?

I'm writing a simple quiz engine in PHP and supply the question text in this format
question|correct/feedback|wrong/feedback|wrong/feedback
There can be as many wrong/feedback options as necessary. I want to use preg_match to return the results so I can display them. For instance:
q|aaa/aaa|bbb/bbb|ccc/ccc
...should return...
array(
0 => q|aaa/aaa|bbb/bbb|ccc/ccc
1 => q
2 => aaa/aaa
3 => bbb/bbb
4 => ccc/ccc
)
So, far I've got this regular expression which matches the question and the correct/feedback combination...
([^\|]+)\|([^\/]+\/[^\|$]+)
...but I have no idea how to match the remaining wrong/feedback strings
You can also use the "glue" feature in your pattern with preg_match_all, this way it's possible to check if the syntax is correct and to extract each part at the same time.
The glue feature ensures that each match follows immediately the previous match without gap. To do that I use the A global modifier (Anchored to the start of the string or the next position after the previous match).
$s = 'q|aaa/aaa|bbb/bbb|ccc/ccc';
$pat = '~ (?!\A) \| \K [^|/]+ / [^|/]+ (?: \z (*:END) )? | \A [^|/]+ ~Ax';
if ( preg_match_all($pat, $s, $m) && isset($m['MARK']) ) {
$result = $m[0];
print_r($result);
}
I use also a marker (*:END) to be sure that the end of the string is well reached despite of the pattern constraints. If this marker exists in the matches array, it's a proof that the syntax is correct. Advantage: you have to parse the string only once (you don't even need to check the whole string syntax in a lookahead assertion anchored at the start of the string).
demo
If you want the whole question as first item in the result array, just write:
$result = array_merge([$s], $m[0]);
So, after the advice, I've decided to use preg_match to check the syntax and then explode to split the string.
This regex seems to match the string format up until any mismatch occurs.
^[^\|/]+(?:\|[^\|/]+/[^\|/]+)+
If I check that the length of the match is the same as the original string I think this will tell me the syntax is correct. Does this sound feasible?

How to preg_match '{95}1340{113}1488{116}1545{99}1364'

i want to preg_match following as it is
$this_string = '{95}1340{113}1488{116}1545{99}1364';
My best try was
preg_match('/^[\{\d+\}\d+]+$/', $this_string);
That matches
{95}1340{113}1488
but also
{95}1340{113}
which is wrong.
I know why it is matching last example. One match {95}1340 was true, so '+' 'll be always true. But i don't know how to tell, if it match, so it has always be a complete match in '[…]'
i do expect only matches likes these
{…}…
{…}…{…}…
{…}…{…}…{…}…
one of the tries:
^(\{\d+\}\d+)+$
does also match
{99}1364
at the very last end of this string as a second match, so i get back an Array with two Elements:
Array[0] = {95}1340{113}1488{116}1545{99}1364 and
Array[1] = {99}1364
Problem is unnecessary use of character class in your regex i.e. [ and ].
You can use:
'/^(\{\d+\}\d+)+$/'
The translation of your regex to a clearer thing would be: /^[\{\}0-9+]+$/, this would be explained as everything that is inside this chracters {}0123456789+, exactly those ones.
What you want is grouping, for grouping, parentheses are needed and not character classes () instead [], so what you want to do is replace [] for ().
Short answer: '/^(\{\d+\}\d+)+$/'
What you are trying to do is a little unclear. Since your last edit, I assume that you want to check the global format of the string and to extract all items (i.e. {121}1231) one by one. To do that you can use this code:
$str = '{95}1340{113}1488{116}1545{99}1364';
$pattern = '~\G(?:{\d+}\d+|\z)~';
if (preg_match_all($pattern, $str, $matches) && empty(array_pop($matches[0])))
print_r($matches[0]);
\G is an anchor for the start of the string or the end of the previous match
\z is an anchor for the end of the string
The alternation with \z is only needed to check that the last match is at the end of the string. If the last match is empty, you are sure that the format is correct until the end.

Match sub-strings that start with a character

I want to match parts of a string that start with a certain character (asterisk):
abc*DEFxyz => *DEF
abc*DE*Fxyz => *DE, *F
Tried preg_match_all('/[$\*A-Z]+/', $string, $matches); But it doesn't seem to work. I get *DE*F on the 2nd example
Change your regex to this :
\*[A-Z]+
http://regexr.com?34itc
Your regex here : [$\*A-Z]+ means a string containing * and A-Z characters, not mentioning anything about start.
Try:
^[^*]*\*
which says "from the start of the line, skip over all non-asterisk characters and stop at the first"
Extending this:
s/^[^*]*\*(.*)/
Will return the remainder of the string after the asterisk. To include the asterisk, adjust like this
s/^[^*]*(\*.*)/
Here's a great tool for checking your regex: http://gskinner.com/RegExr/
Hope this helps

Regex to get string from last numeric values

I have some php string like below
abc-1987-mp3-songs
xyz-1999-india-mp3-songs
dec-2001-mp3-songs
ryu-2012-freemp3-songs
Now I want these string splited at last found numeric values like below
abc-1987
xyz-1999
dec-2001
ryu-2012
Please help me that which regex can be used to do this. thanks.
Ok, I had a look (do take some time to learn regex - but meanwhile):
$split = (preg_split('/(^.*?[0-9]+)\-?[^0-9]+/', 'foo-xyz-1999-india-mp3-songs', -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));
echo $split[0];//<--- foo-xyz-1999, just like you wanted
Dumps an array with foo-xyz-1999 as first value, which is what you need. If you want to know what every part of the regex does read it here
The only difference is that, though the whole string becomes its own delimiter, there are two delimiters (the first part, always ending on a series of numbers and the rest of the string, that doesn't contain any more digits)
Use explode insted of regular expression
for example:-
$str="abc-1987-mp3-songs";
$f=explode("-",$str);
echo $final_result=$f[0]."-".$f[1];
or if you want to use reg exp.then
<?php
$str="abc-1987-mp3-songs";
echo $f=preg_replace('/[^0-9]/','', $str);
?>
Above code give you all the numeric digits of your string.
This would match last occurrence of numeric value from given string:
([\w\d-]*-[\d]+)
This is the link: Regex

Replacing a string using preg_match

I'm having trouble using preg_match to find and replace a string. The string of interest is:
<span style="font-size:0.6em">EXPIRATION DATE: 04/30/2011</span>
I need to target and replace the date, "04/30/2011" with a different date. Can someone throw me a bone a give me the regular expression to match this pattern using preg_match in PHP? I also need it to match in such a way that it only replaces up to the first closing span and not closing span tags later in the code, e.g.:
<span style="font-size:0.6em">EXPIRATION DATE: 04/30/2011</span><span class="hello"></span>
I'm not versed in regex, and although I've spent the last hour trying to learn enough to make this work, I'm utterly failing. Thanks so much!
EDIT: As you can see this has gotten me exhausted. I did mean preg_replace, not preg_match.
If you're after a replacement, consider using preg_replace(), something like
preg_replace('#(\d{2})/(\d{2})/(\d{4})#', '<new date>', $string);
How about this:
$toBeFoundPattern = '/([0-9][0-9])\/([0-9][0-9])\/([0-9][0-9][0-9][0-9])/';
$toBeReplacedPattern = '$2.$1.$3';
$inString = '<span style="font-size:0.6em">EXPIRATION DATE: 04/30/2011</span>';
// Will convert from US date format 04/30/2011 to european format 30.04.2011
echo preg_replace( $toBeFoundPattern, $toBeReplacedPattern, $inString );
and prints
EXPIRATION DATE: 30.04.2011
Patterns always begin and end with identical so called delimiter characters. Often the character / is used.
$1 references the string, which matched the first string matched by ([0-9][0-9]), $2 references be (...) and $3 the four letters matched by the last (...).
[...] matched a single character, which is one of those listed inside the brackets. E.g. [a-z] matches all lower case letters.
To use the special meaning character / inside of a pattern, you need to escape it by \ to make it be the literal slash character.
Update: Using {..} as pointed out below is shorthand for repeated patterns.
Regex should be:
(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d
If you want to only match one instance, this is OK. For multiple instances, use preg_match_all instead. Taken from http://www.regular-expressions.info/regexbuddy/datemmddyyyy.html.
Edit: are you looking to just search and replace inside a PHP script or do you want to do some javascript live replacement?

Categories