我有一些从旧的access数据库导出的文本字段,正在转移到新的MySQL结构中。它们的格式为:
10/06/2010 09:10:40 工作尚未开始
我想使用某种正则表达式提取日期/时间信息和之后的注释。
是否有一个简单的正则表达式语法可以匹配这些信息?
$parts = explode(" ", $string, 3);
preg_match('|^([0-9]{2})/([0-9]{2})/([0-9]{4})\s([0-9]{2}):([0-9]{2}):([0-9]{2})\s(.*)$|',$str,$matches);
list($str,$d,$m,$y,$h,$m,$s,$comment)=$matches;
我认为,您可以直接使用现有的空格作为分隔符,得到以下表达式:
/([^ ]+) ([^ ]+) (.+)/
\S
匹配任何非空白,其中空白可以是空格、制表符或换行符。相比之下,我的表达式仅限于空格字符。根据上下文,\S
可能更可取,但我不想猜测确切的上下文。 - Konrad Rudolph在正则表达式比较耗费资源的情况下。如果这种格式一直被保证存在,你可以通过两个空格进行分割,并使用前两个切片如下:
$str = "10/06/2010 09:10:40 Work not yet started";
$slices = explode(" ", $str, 3);
$timestamp = strtotime($slices[0] . $slices[1]);
echo "String is $str\n";
echo "Timestamp is $timestamp\n";
echo "Timestamp to date is " . strftime("%d.%m.%Y %T", $timestamp) . "\n";
如果您的日期/时间存储为datetime
类型,那么您可以使用类似以下的代码:
preg_match("/^([0-9\\/]{10} [0-9:]{8}) (.*)$/",$str,$matches);
$datetime = $matches[1];
$description = $matches[2];
preg_match("/^([0-9\\/]{10}) ([0-9:]{8}) (.*)$/",$str,$matches);
$date = $matches[1];
$time = $matches[2];
$description = $matches[3];
list($date,$time,$description) = explode(' ',$str,3);
另一个选项是,假设日期和时间始终具有相同的长度:
$date = substr($str,0,10);
$time = substr($str,11,19);
$description = substr($str,20);
if(preg_match('([0-9/]+ [0-9:]+)', $myString, $regs)) {
$myTime = strtotime($regs[1]);
}
([0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}\s[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})\s(.*)
// sample string you provided
$string = "10/06/2010 09:10:40 Work not yet started";
// regular expression to use
$regex = "/^(\d+)\/(\d+)\/(\d+) (\d+)\:(\d+)\:(\d+) (.+?)$/";
现在,你想要的所有字段都在数组$matches中。 要将信息提取到数组$matches中,可以使用preg_match()函数。
// method 1: just extract
preg_match($regex, $string, $matches);
// method 2: to check if the string matches the format you provided first
// then do something with the extracted text
if (preg_match($regex, $string, $matches) > 0) {
// do something
}
为了进一步利用你所获得的信息:
// to get a Unix timestamp out of the matches
// you may use mktime()
// method 1: supposed your date format above is dd/mm/yyyy
$timestamp = mktime($matches[4], $matches[5], $matches[6],
$matches[2], $matches[1], $matches[3]);
// method 2: or if your date format above is mm/dd/yyyy
$timestamp = mktime($matches[4], $matches[5], $matches[6],
$matches[1], $matches[2], $matches[3]);
然后您可能想要查看时间是否被正确解析:
print date('r', $timestamp)
$comment = $matches[7];
注意时区问题。如果您在生成数据的同一台服务器上解析这些数据,那么您很可能不会有问题。您可能需要从上面的时间戳中添加/减去时间。
$s = '10/06/2010 09:10:40 Work not yet started';
$date = substr($s, 0, 19);
$msg = substr($s, 20);
$date = strtotime($date);
// or
$date = strptime($date, "%m/%d/%Y %H:%M:%S");
有没有一个简单的正则表达式语法可以匹配这些信息?
是的,有。这是一个“提取”而不是“验证”的练习。你想要在紧随日期时间表达式的空格上仅拆分字符串一次,以形成确切的两个元素。首先匹配日期,然后是空格,然后是时间,然后忘记所有已匹配的内容(`\K`元字符-- 重新启动全字符串匹配),然后匹配用作分隔符的空格。
限制爆炸,以便即使评论中有空格,也只生成两个元素。
代码:(演示)
$string = '10/06/2010 09:10:40 Work not yet started';
var_export(preg_split('/\S+ \S+\K /', $string, 2));
输出:
array (
0 => '10/06/2010 09:10:40',
1 => 'Work not yet started',
)
不需要捕获组,并且preg_match()
不是很理想,因为它在输出中创建了过多的数据。preg_split()
是最直接提供所需输出的单一函数技术。如果这是我的项目,我不会使用其他方法。