Regular expression and create substring for time - php

I need a regular for time format HH:MM am/pm. I found something like
$time = "HH:MM am";
preg_match('/[\s0]*(\d|1[0-2]):(\d{2})\s*([AaPp][Mm])/xms', $time, $match);
$h = $match[1];
$m = $match[2];
$a = $match[3];
There are lot of regular expression for time. But what i am looking is if someone write aa:mn jk instead of number then it should give $h=aa $m=mn and $a=jk Or if someone keep them blank or partial filled like abcd then $h=abcd $m=null and $a=null.
I solved it using for loop and some if else but hope some can help me to do it using regular expression or using some PHP function.

You're going to need regexp like this ~^(\d{1,2})((?::)(\d{1,2}))?(\s+(am|pm))?$~i
The whole testing code would be:
<?php
$regexp = '~^(\d{1,2})((?::)(\d{1,2}))?(\s+(am|pm))?$~i';
$tests = array(
'18',
'18:00',
'7:03 pm',
'7 pm'
);
$match = array();
foreach( $tests as $test){
preg_match( $regexp, $test, $match);
print_r( $match);
}
And the results:
Array
(
[0] => 18
[1] => 18
)
Array
(
[0] => 18:00
[1] => 18
[2] => :00
[3] => 00
)
Array
(
[0] => 7:03 pm
[1] => 7
[2] => :03
[3] => 03
[4] => pm
[5] => pm
)
Array
(
[0] => 7 am
[1] => 7
[2] =>
[3] =>
[4] => am
[5] => am
)
So you can prepare you final output like:
$hours = isset( $match[1]) ? $match[1] : '00';
$minutes = isset( $match[3]) ? $match[3] : '00';
$am = isset( $match[5]) ? $match[5] : 'am';
If you need explanation of anything please ask in the comment

Using Regex might be a little overkill. Use the explode() function instead.
<?php
$str = 'aa:bb cc'; // or 'abcd'
$a = explode(':', $str);
$b = isset($a[1]) ? explode(' ', $a[1]) : NULL;
$h = $a[0];
$m = isset($b[0]) ? $b[0] : NULL;
$a = isset($b[1]) ? $b[1] : NULL;
var_dump($h, $m, $a);

You were very vague about your requirements, so I don't really know what you're trying to match, but this will match any number of non-: characters and stick it in $h, followed by an optional : and non-space characters which will be put in $m, followed by an optional 0 or more spaces and the remaining characters will be put in $a:
if (!preg_match('/^([^:]+)(:(\S+))?(\s*(.+))?$/i', $input, $matches)) {
// pattern did not match
}
$h = $matches[1];
$m = $matches[3] ?: NULL;
$a = $matches[5] ?: NULL;

Related

How to use explode function for finding the result like this? and please explain the meaning of each $delimiter used inside the explode function

My input is $text = '( ( LED AND DIODE ) OR ( "LEE power" and system ) ) '
I am applying explode function on this input
function multiexplode ($delimiters,$string)
{
$ready = str_replace($delimiters, $delimiters[0], $string);
$launch = explode($delimiters[0], $ready);
return $launch;
}
$exploded = multiexplode(array(' ',":" ), $text);
for($i=0;$i<(count($exploded));$i++)
echo "<br> $exploded[$i]";
My output is coming like this
0 - (
1 - (
2 - LED
3 - AND
4 - DIODE
5 - )
6 - OR
7 - (
8 - "LEE
9 - power"
10 - and
11 - system
12 - )
13 - )
But I want to output like the following
0 - (
1 - (
2 - LED
3 - AND
4 - DIODE
5 - )
6 - OR
7 - (
8 - LEE power
9 - and
10 - system
11 - )
12 - )
I want to store all words inside " " in one element of array.
Check the following code:
$text = '( ( LED AND DIODE ) OR ( "LEE power" and system ) ) ';
preg_match_all('/"(?:\.|[^"])*"|\S+/', $text, $exploded);
for($i=0;$i<(count($exploded[0]));$i++)
echo "<br>". $exploded[0][$i];
UPDATE based on comment
For input of $text = '((LED AND DIODE) OR ("LEE power" and system)) ';
$text = '((LED AND DIODE) OR ("LEE power" and system)) ';
$re = '/"(?:\.|[^"])*"|\(?|\)|(\'(.*?)\'|(\w+))/';
preg_match_all($re, $text, $exploded);
for($i=0;$i<(count($exploded[0]));$i++)
if($exploded[0][$i]!='')
echo "<br>". $exploded[0][$i];
While this isn't a thoroughly-tested answer, this answers your current issue as you described it. Best of luck!
function concatenateQuotedElements($input_array)
{
//As per the question, we'll be exploding our array by spaces " ".
$pieces = explode(" ", $input_array);
//This array will be returned as our final array of concatenated elements.
$output_array = array();
/*When we happen upon an element containing a
parenthesis ('"') as the first character, we'll
temporarily store so that we may concatenate
future elements with it.*/
$stored_element = null;
$stored_position = null;
/*Parse through our array and look for any character
that contains a " and see whether it's at the beginning
or the end of the string element.*/
for ($i = 0; $i < count($pieces); $i++)
{
//If we detect a parenthesis in our element...
if (strpos($pieces[$i], '"') !== false)
{
//See if it's at the beginning, and if it is, store it or future use.
if (substr($pieces[$i], 0, 1) === '"')
{
$stored_element = $pieces[$i];
$stored_position = $i;
}
/*Or, see if it's at the end of the string. If it is, we need to see
if there's been a previous element with an opening parenthesis that
we've stored and concatenate this element onto our stored element.*/
if (
substr($pieces[$i], -1) === '"' &&
$stored_element !== null &&
$stored_position !== null
)
{
$output_array[$stored_position] = $stored_element . " " . $pieces[$i];
/*Reset our temporary storage so that it hold
any forthcoming elements with parenthesis.*/
$stored_element = null;
$stored_position = null;
/*Finally, [Continue] to the next element without
pushing this as a non-concatenated, standalone element.*/
continue;
}
}
array_push($output_array, $pieces[$i]);
}
return $output_array;
}
For a specific output pertaining to your given array, you can use:
//Our example array given in the question:
$array = '( ( LED AND DIODE ) OR ( "LEE power" and system ) )';
//Our output:
$concatenate_quotes_array = concatenateQuotedElements($array);
//"Pretty print" the array result of the function
echo "<pre>";
print_r($concatenate_quotes_array);
echo "</pre>";
Output:
Array
(
[0] => (
[1] => (
[2] => LED
[3] => AND
[4] => DIODE
[5] => )
[6] => OR
[7] => (
[8] => "LEE power"
[9] => and
[10] => system
[11] => )
[12] => )
)
here
<?php
$text = str_replace('LEE power','LEE-power',"( ( LED AND DIODE ) OR ( 'LEE power' and system ) ) ");
$newArray = explode(' ',$text);
foreach($newArray as $row) $data[] = str_replace('-',' ',$row);
echo "<pre>";print_r($data);die;
?>

php from a string get or print specialchar, number, alphabetic seprate seprate in php

I have a string like:
$str = "hello#$how%&*!are345You^_THere56";
I want that alphabet stores in one variable like:
hello,how,are,you,THere
Number should be stored in one variable like:
3,4,5,5,6
special characters separately:
#$%&*!^_
How can I do this?
In my opinion, the best choice for this is to use preg_split:
<?php
$str = 'hello#$how%&*!are345You^_THere56';
$words = array_filter(preg_split('/[^a-zA-Z]/', $str));
$numbers = str_split(join('', preg_split('/[^0-9]/', $str)));
$specials = str_split(join('', preg_split('/[a-zA-Z0-9]/', $str)))
print_r($words);
print_r($numbers);
print_r($specials);
By negating character classes we can filter the results how we want. The str_split an join calls are to split on character basis rather than on group basis.
Results:
Array
(
[0] => hello
[2] => how
[6] => are
[9] => You
[11] => THere
)
Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 5
[4] => 6
)
Array
(
[0] => #
[1] => $
[2] => %
[3] => &
[4] => *
[5] => !
[6] => ^
[7] => _
)
You could check for regex match.
$str = "hello#$how%&*!are345You^_THere56";
for($i=0; $i<strlen($str ); $i++)
if($str[$i] == "^[0-9]*$") {
//store numbers
}
else-if($str[$i] == "^[a-zA-Z]*$") {
// store characters
}
else {
//store special characters
}
Try this
$strs = '';
$num = '';
$sc = '';
$str = 'hello#$how%&*!are345You^_THere56';
$a = str_split($str);
$prev = '';
foreach($a as $v){
switch($v){
case is_numeric($v):
$num .= $v;
break;
case preg_match('/[a-zA-Z]/',$v):
$sc .= $v;
break;
default:
$strs .= $v;
break;
}
$prev = $v;
}
echo "<p>";
echo "<p>Strings: ".$strs."</p>";
echo "<p>Numbers: ".$num."</p>";
echo "<p>Special Characters: ".$sc."</p>";

What is the best way to split letters and numbers?

I have this variable:
$str = "w15";
What is the best way to split it to w and 15 separately?
explode() is removing 1 letter, and str_split() doesn't have the option to split the string to an unequal string.
$str = "w15xx837ee";
$letters = preg_replace('/\d/', '', $str);
$numbers = preg_replace('/[^\d]/', '', $str);
echo $letters; // outputs wxxee
echo $numbers; // outputs 15837
You could do something like this to separate strings and numbers
<?php
$str = "w15";
$strarr=str_split($str);
foreach($strarr as $val)
{
if(is_numeric($val))
{
$intarr[]=$val;
}
else
{
$stringarr[]=$val;
}
}
print_r($intarr);
print_r($stringarr);
Output:
Array
(
[0] => 1
[1] => 5
)
Array
(
[0] => w
)
If you want it to be as 15 , you could just implode the $intarr !
Use preg_split() to achieve this:
$arr = preg_split('~(?<=\d)(?=[a-zA-Z])|(?<=[a-zA-Z])(?=\d)~', $str);
Output:
Array
(
[0] => w
[1] => 15
)
For example, the string w15g12z would give the following array:
Array
(
[0] => w
[1] => 15
[2] => g
[3] => 12
[4] => z
)
Demo
Much cleaner:
$result = preg_split("/(?<=\d)(?=\D)|(?<=\D)(?=\d)/",$str);
Essentially, it's kind of like manually implementing \b with a custom set (rather than \w)

PHP find positions of all occurrences of a particular word in a string

This is slightly different to finding all the positions of a substring inside a string because I want it to work with words which may be followed by a space, comma, semi-colon, colon, fullstop, exclamation mark and other punctuation.
I have the following function to find all the positions of a substring:
function strallpos($haystack,$needle,$offset = 0){
$result = array();
for($i = $offset; $i<strlen($haystack); $i++){
$pos = strpos($haystack,$needle,$i);
if($pos !== FALSE){
$offset = $pos;
if($offset >= $i){
$i = $offset;
$result[] = $offset;
}
}
}
return $result;
}
Problem is, if I try to find all positions of the substring "us", it will return positions of the occurrence in "prospectus" or "inclusive" etc..
Is there any way to prevent this? Possibly using regular expressions?
Thanks.
Stefan
You can capture offset with preg_match_all:
$str = "Problem is, if I try to find all positions of the substring us, it will return positions of the occurrence in prospectus or inclusive us us";
preg_match_all('/\bus\b/', $str, $m, PREG_OFFSET_CAPTURE);
print_r($m);
output:
Array
(
[0] => Array
(
[0] => Array
(
[0] => us
[1] => 60
)
[1] => Array
(
[0] => us
[1] => 134
)
[2] => Array
(
[0] => us
[1] => 137
)
)
)
Just to demonstrate a non regexp alternative
$string = "It behooves us all to offer the prospectus for our inclusive syllabus";
$filterword = 'us';
$filtered = array_filter(
str_word_count($string,2),
function($word) use($filterword) {
return $word == $filterword;
}
);
var_dump($filtered);
where the keys of $filtered are the offset position
If you want case-insensitive, replace
return $word == $filterword;
with
return strtolower($word) == strtolower($filterword);

Preg_match return array of positions of each match with PREG_OFFSET_CAPTURE

Having trouble returning an array of positions:
function returnPosition($string,$start){
preg_match('/' . preg_quote($start, '/').'/im', $string, $m, PREG_OFFSET_CAPTURE);
$startArr = array();
foreach ($m as $value)
{
$startArr = array_push($startArr, $m);
}
//var_dump($startArr);
return $startArr;
}
Thanks
No surprise, you're using array_push wrong. It does NOT return the modified array. It returns the new number of elements in the array, so on each iteration you're trashing what used to be an array with an int. Try
$startArr[] = $m;
or at least just
array_push($startArr, $m);
with no assignment at all.
Found something that works for me:
function getTagPositions($strBody, $start, $end)
{
preg_match_all('/' . preg_quote($start, '/') . '([\w\s.]*?)'. preg_quote($end, '/').'/im', $strBody, $strTag, PREG_PATTERN_ORDER);
$intOffset = 0;
$intIndex = 0;
$intTagPositions = array();
foreach($strTag[0] as $strFullTag) {
$intTagPositions[$intIndex] = array('start' => (strpos($strBody, $strFullTag, $intOffset)), 'end' => (strpos($strBody, $strFullTag, $intOffset) + strlen($strFullTag)));
$intOffset += strlen($strFullTag);
$intIndex++;
}
return $intTagPositions;
}
$intTagPositions = getTagPositions("hello there hello hello","he","lo");
// returns
Array ( [0] => Array ( [start] => 0 [end] => 5 ) [1] => Array ( [start] => 7 [end] => 17 ) [2] => Array ( [start] => 18 [end] => 23 ) )

Categories