2010-06-21 8 views
3

J'ai un certain nombre de champs de texte exportés d'une ancienne base de données d'accès qui sont en cours de portage dans une nouvelle structure mysql. Il y a plusieurs entrées sur le terrain dans le format:PHP Expression régulière pour extraire l'horodatage et le commentaire

10/06/2010 09:10:40 pas encore commencé

Je voudrais prendre cette chaîne et utiliser une sorte d'expression régulière extraire les informations de date/heure, puis le commentaire après.

Existe-t-il une simple syntaxe d'expression régulière pour faire correspondre cette information?

Merci

+0

Pourquoi regex? On dirait que vous avez des longueurs de champs fixes plus un format de date assez standard. –

Répondre

2

Je pense que je vais avoir un aller ce

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; 

vous avez alors les valeurs nécessaires pour reconstruire le temps dans n'importe quel format.

3

Comme je le vois, vous pouvez simplement utiliser les espaces existants comme délimiteurs, ce qui donne l'expression suivante:

/([^ ]+) ([^ ]+) (.+)/ 

C'est: trois groupes séparés par des espaces, dont les deux premiers les groupes ne contiennent aucun espace (mais le troisième peut).

+0

Peut-être que cette notation n'existe pas en php mais ne serait-il pas préférable de faire \ S + pour les non-espaces au lieu de [^] + –

+0

@stocherilac: Je préfère être précis. '\ S' correspond à tout espace non-blanc, où les espaces peuvent être un espace, une tabulation ou un saut de ligne. En revanche, mon expression * seulement * permet le caractère d'espace. Selon le contexte, '\ S' peut être préférable, mais je ne veux pas deviner le contexte exact. –

+0

Oui, je comprends cela, juste en vérifiant :) –

7

Vous pouvez utiliser ce lieu d'une expression rationnelle:

$parts = explode(" ", $string, 3); 
+0

Cela fonctionnerait si tous les champs étaient dans le même format, hélas certains champs sont en dehors de ce format et me donneraient un jeu de données douteux. L'utilisation d'un preg_match me permet d'utiliser une instruction conditionnelle qui est avantageuse. Sinon, cela aurait parfaitement fonctionné, merci. – simnom

0
if(preg_match('([0-9/]+ [0-9:]+)', $myString, $regs)) { 
    $myTime = strtotime($regs[1]); 
} 
0

Si vous voulez juste extraire 2 chaînes, vous pouvez utiliser:

([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(.*) 
1

Eh bien, si votre date/heure est stockée en tant que type datetime, vous pouvez alors utiliser quelque chose comme

preg_match("/^([0-9\\/]{10} [0-9:]{8}) (.*)$/",$str,$matches); 
$datetime = $matches[1]; 
$description = $matches[2]; 

Si vous stockerez la date/heure séparément, vous pouvez utiliser

preg_match("/^([0-9\\/]{10}) ([0-9:]{8}) (.*)$/",$str,$matches); 
$date = $matches[1]; 
$time = $matches[2]; 
$description = $matches[3]; 

Bien sûr, une alternative à Regula expressions r est de faire exploser la chaîne:

list($date,$time,$description) = explode(' ',$str,3); 

Et une autre option, en supposant que les dates et les heures sont toujours la même longueur:

$date = substr($str,0,10); 
$time = substr($str,11,19); 
$description = substr($str,20); 
2

Dans les circonstances regex est cher. Si cela est le format toujours garanti d'être là, vous pouvez diviser par 2 espaces et d'utiliser les 2 premières tranches comme suit:

$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"; 
+1

"Dans les circonstances, regex est cher" - avez-vous des repères pour soutenir cette revendication scandaleuse? Les expressions régulières sont beaucoup plus rapides que la plupart des gens prétendent/réalisent, et en particulier, ils se comportent relativement bien dans les langues dynamiques. Et last but not least, c'est une optimisation prématurée. Cela dit, l'option 'explode' (qui a déjà été mentionnée) est une très bonne alternative. –

0

Vous pouvez extraire les informations avec le code ci-dessous:

// 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+) (.+?)$/"; 

Maintenant, tous les champs que vous voulez sont dans le tableau $ matches. Pour extraire des informations dans les matchs de tableau $, vous pouvez utiliser 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 
} 

Pour utiliser plus les informations que vous avez:

// 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]); 

Ensuite, vous voudrez peut-être voir si le temps est correctement parsé:

print date('r', $timestamp) 

enfin, obtenir le commentaire comme celui-ci:

$comment = $matches[7]; 

Soyez conscient du problème de fuseau horaire. Si vous analysez ces données sur le même serveur que celui qu'elles ont généré, cela fonctionnera probablement très bien. Vous devrez peut-être ajouter/soustraire l'heure de l'horodateur ci-dessus.

0
$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"); 
Questions connexes