我正在编写一个从外部世界接收数据的脚本,我在其中查看事件发生的时间,例如两组时间是:
Mon - Fri: 12:00 - 14:00, 18:00 - 22:30, Sat: 18:00 - 22:00
Tue, Wed, Thu: 17:30 - 23:00, Sat: 12:00 - 17:00, Sun: 17:00 - 22:30
正如您所看到的,在每种情况下,数据都以不同的方式显示(mon fri或tues、wed、thu(。有人能给我一些关于编写正则表达式/处理形式以将数据放入数组的建议吗,例如:
$timing['mon'][1]['start'] = '12:00';
$timing['mon'][1]['finish'] = '14:00';
$timing['mon'][2]['start'] = '18:00';
$timing['mon'][2]['finish'] = '22:30';
提前谢谢。。
我想试试看。
我假设这两条不同的线是两种不同的输入。并没有真正为错误检查而烦恼。因此,如果格式与您提供的示例有很大不同,那么这很可能会失败。
<?php
/**
* Gets the days of the week in a range. e.g. given Mon Wed, will return an
* array of Mon, Tue, Wed
* @param string $start 3 letter day of the week (ucfirst)
* @param string $end 3 letter day of the week (ucfirst)
* @return array The days from $start to $end
*/
function get_day_range($start, $end) {
if ($start == $end)
return array($start);
$date = new DateTime($start);
$days = array($start);
while($date->format('D') != $end){
$date->modify('+1 day');
$days[] = $date->format('D');
}
return $days;
}
/**
* Checks if the needle exists in the haystack
* @param string $needle
* @param string $haystack
* @return bool
*/
function instr($needle, $haystack) {
return strpos($haystack, $needle) !== false;
}
function get_event_times($input) {
preg_match_all('/
(?<days>(
(Mon|Tue|Wed|Thu|Fri|Sat|Sun)
's*[-,]?'s*
)+):'s
(?<times>
(
(
'd'd:'d'd
's-'s
'd'd:'d'd
),?'s*
)+
)/x', $input, $matches, PREG_SET_ORDER);
$return = array();
foreach($matches as $match) {
$days = $match['days'];
// Is a day range
if (instr(' - ', $days)) {
list($start, $end) = explode(' - ', $days, 2);
$days = get_day_range($start, $end);
}
// Is a list of days
elseif (instr(', ', $days)) {
$days = explode(', ', $days);
}
// Is just one day
else {
$days = array($days);
}
$times = trim($match['times'], ', ');
$times = explode(', ', $times);
foreach($days as $day) {
foreach($times as $time) {
list($start, $end) = explode(' - ', $time);
$return[$day][] = array(
'start' => $start,
'end' => $end
);
}
}
}
return $return;
}
$inputs = array(
'Mon - Fri: 12:00 - 14:00, 18:00 - 22:30, Sat: 18:00 - 22:00',
'Tue, Wed, Thu: 17:30 - 23:00, Sat: 12:00 - 17:00, Sun: 17:00 - 22:30'
);
foreach($inputs as $input) {
var_dump(get_event_times($input));
}
<?php
$string = "Mon - Fri: 12:00 - 14:00, 18:00 - 22:30, Sat: 18:00 - 22:00
Tue, Wed, Thu: 17:30 - 23:00, Sat: 12:00 - 17:00, Sun: 17:00 - 22:30";
preg_match_all("/([a-zA-Z'-'s',]+): ([0-9':','s'-]+)/", $string, $matches, PREG_OFFSET_CAPTURE);
$data = array();
foreach ($matches[1] as $key => $day){
//Split the data and remove whitespace.
$values = explode(",", $matches[2][$key][0]);
foreach ($values as $a => $b) $values[$a] = trim($b); if (empty($values[$a])) unset($values[$a]);
//Loop each set and split the stand and end.
foreach ($values as $a => $b){
$splits = explode("-", $b);
$values[$a] = array("Start" => $splits[0], "End" => $splits[1]);
} //end foreach
//Place the new data in the array.
$data[trim($day[0])] = $values;
} //end foreach
echo "<pre>";
print_r($data);
?>
上面的代码将允许更改您的数据,正如您所注意到的,根据您的数据来看,数组中的键将保持为"Mon-Fri",因为它的格式没有标准,似乎无论如何都会更改。
您需要的不仅仅是正则表达式来解决这个问题。我会先把它分成小块。由于分隔符在这种格式中起着双重(或三重(的作用,所以您不能只将其按分隔符进行分解,因此需要对其进行块处理。首先,我会把第一个冒号前后的所有内容都拆开。第一部分是日期说明符,所以解析它——如果它是逗号分隔的列表,只需将其拆分为键列表即可。如果是范围,则使用循环构建键列表。之后,你会有一个时间列表。我会循环类似'd'd:'d'd - 'd'd:'d'd,?
的东西,直到它不匹配为止(指示行的末尾或另一个条目(,将每个间隔应用于您之前生成的键集,并对那里的第二个索引进行增量计数。一旦这种模式不匹配,就重新开始整个过程:
- 拆分到第一个冒号以获得日期说明符
- 将日期说明符处理为一个列表或一个范围(在破折号上匹配可能可以判断您有哪种情况(到一个日期列表中
- 使用下一个逗号或字符串末尾(或使用时间范围模式(来获取时间范围
- 将该时间范围应用于步骤2中的天数列表
- 如果存在其他时间模式,则循环回3,否则循环回1