Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум Регулярные Выражения

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Помогите с простейшим приведением формата времени :)
 
 автор: Ptr73   (05.02.2010 в 10:11)   письмо автору
 
 

Приветствую!
В регулярных выражениях я полный нуб, так что прошу элементарной помощи.
Нужно распарсить строку с временами и привести ее к формату "чч:мм:сс"
Строка наподобие такой:
1:10:50 1:28 13:41 14:23:10 2:12 1:44
нужно получить список значений
01:10:50; 00:01:28; 00:13:41; 14:23:10;
любыми методами, но предпочтительно если стандартными методами регулярных выражений и замены по шаблону,
т.к. делаю я это не на php, а на VBA через regexp и regexp.replace :)

Заранее благодарен!

  Ответить  
 
 автор: heed   (05.02.2010 в 11:01)   письмо автору
 
   для: Ptr73   (05.02.2010 в 10:11)
 

а там в VBA бывает replace с возможностью вместо строки замены поставить функцию
, или хотя-бы выражения с /e чтобы сделать eval() в строке замены ?

на php можно просто vsprintf() например поиспользовать, можно и без него но тоже с /e или callback-функцией
<?php
$txt 
'1:10:50 1:28 13:41 14:23:10 2:12 1:44';

echo 
preg_replace('#(?:(\d+):)?(\d+)(:\d+)#e'
'vsprintf("%02d", "$1") .":". vsprintf("%02d", "$2") ."$3"'$txt) . "\n\n";

  Ответить  
 
 автор: Ptr73   (05.02.2010 в 11:19)   письмо автору
 
   для: heed   (05.02.2010 в 11:01)
 

На VB есть RegExp.Replace с паттернами

Вот пример, хотя я сам не очень понимаю сути использованных паттернов:

str1 = "The quick brown fox jumped over the lazy dog."
regEx.Pattern = "(\S+)(\s+)(\S+)" ' Определяем шаблон.
ReplaceTest = regEx.Replace(str1, "$3$2$1") ' Меняем попарно слова местами

то есть тут два паттерна:
"(\S+)(\s+)(\S+)" - для поиска
"$3$2$1" - для замены

я думаю, что это стандартные методы для регулярных выражений

  Ответить  
 
 автор: heed   (05.02.2010 в 11:43)   письмо автору
 
   для: Ptr73   (05.02.2010 в 11:19)
 

похоже на preg
, но даже например получив цифры так
regEx.Pattern = "(\d+)?:?(\d+):(\d+)"
ReplaceTest = regEx.Replace(str1, "$1:$2:$3")
, если так их можно получить, нужно-же анализировать полученное , и добавлять нули, если нужно
, а это простой перестановкой не решается

нужно смотреть доки по regEx.Replace, на предмет возможности ставить функции вторым параметром
, или возможно используются просто циклы с каким-нибудь regEx.Exec или regEx.Match
И возможно даже вообще есть специальные функции для работы со временем, или хотя-бы просто функции форматированного вывода.

обычно просто не кузяво использовать какие-нибудь "(?:(\d)?(\d):)?(\d)?(\d):(\d+)" такие выражения, результат которых тоже придётся просматривать на наличие всяких $1 $2 $3 $4 $5

  Ответить  
 
 автор: Ptr73   (05.02.2010 в 11:50)   письмо автору
 
   для: heed   (05.02.2010 в 11:43)
 

Спасибо!
Попробую разобраться.
А в VB большая проблема в функциях времени - значения вида мм:сс он воспринимает как чч:мм,
собственно поэтому я и привожу все времена к единому формату

  Ответить  
 
 автор: Trianon   (05.02.2010 в 13:14)   письмо автору
 
   для: Ptr73   (05.02.2010 в 11:50)
 

>А в VB большая проблема в функциях времени - значения вида мм:сс он воспринимает как чч:мм,
>собственно поэтому я и привожу все времена к единому формату

Именно VB воспринимает? :)
Знаете, если человек на вопрос "что здесь написано?"
12:34
ответит "12 минут 34 секунды", и на него посмотрят, как на кандидата в дурку - я не удивлюсь.

  Ответить  
 
 автор: Ptr73   (05.02.2010 в 13:26)   письмо автору
 
   для: Trianon   (05.02.2010 в 13:14)
 

Ну как сказать, как сказать.
Я пишу программу для обработки спортивных результатов.
И если окажется, что например биатлонист бежал очередной круг с результатом 12 часов 34 минуты, то тогда на этого биатлониста посмотрят не как на спортсмена, а как на кандидата в дурку :)
Проблема в том, что в VB нельзя явно указать формат используемых временных данных, поэтому при преобразованиях разноформатных времен постоянно возникают проблемы.

  Ответить  
 
 автор: Trianon   (05.02.2010 в 13:57)   письмо автору
 
   для: Ptr73   (05.02.2010 в 13:26)
 

Всё верно.
Вы работаете в рамках специфического контекста задачи.
И Вам, как программисту, его особенности и приходится реализовывать универсальными [более или менее] инструментами.

  Ответить  
 
 автор: Ptr73   (05.02.2010 в 13:43)   письмо автору
 
   для: heed   (05.02.2010 в 11:43)
 

Еще раз спасибо!
Сделал, хотя и не настолько красиво, насколько рассчитывал.
К сожалению, без цикла не обошлось.

примерно так:

timestr = "1:10:50 1:28 13:41 14:23:10 2:12 1:44"
regex.Pattern = "(?:(\d)?(\d):)?(\d)?(\d):(\d+)"

Set matches = regex.Execute(timestr)

For i = 0 To matches.Count - 1

        timeline = timeline + CStr(Int(matches(i).SubMatches(0))) + CStr(Int(matches(i).SubMatches(1))) + ":" + CStr(Int(matches(i).SubMatches(2))) + CStr(Int(matches(i).SubMatches(3))) + ":" + CStr(Int(matches(i).SubMatches(4))) + "; "

Next i

  Ответить  
 
 автор: big-trot   (05.02.2010 в 19:31)   письмо автору
 
   для: Ptr73   (05.02.2010 в 13:43)
 

Для полной точности предлагается

\b(?:(\d)?(\d):)?((\d)?(\d):)?(\d+)

иначе ваш патерн найдет совпадение при 333:333:333
и не найдет "999", хотя это могут быть милесекунды.

  Ответить  
 
 автор: big-trot   (05.02.2010 в 21:17)   письмо автору
 
   для: Ptr73   (05.02.2010 в 13:43)
 

Предлагается на обсуждение следующий вариант, который позволяет осекать на правильный формат времени тип 44:66:00. В данном варианте младшие разряды всегда относятся к милисекундам. Если знать контекст поиска, то регулярное выражение можно упрастить. Регулярное выражение составленное на все случаи жизни, которые можно вообразить, не бывает простым.

(?:\b(?<!:)\d+(?!:)\b)|(\b(?<!:)[0-5]?[\d]:\d+(?!:)\b)|(\b(?<!:)[01]?[\d]:[0-5]?[\d]:\d+(?!:)\b)

  Ответить  
 
 автор: Ptr73   (06.02.2010 в 09:25)   письмо автору
 
   для: Ptr73   (05.02.2010 в 10:11)
 

big-trot
(?:\b(?<!:)\d+(?!:)\b)|(\b(?<!:)[0-5]?[\d]:\d+(?!:)\b)|(\b(?<!:)[01]?[\d]:[0-5]?[\d]:\d+(?!:)\b)

VB не может переварить, выдает ошибку при обработке паттерна

\b(?:(\d)?(\d):)?((\d)?(\d):)?(\d+)

на 333:333:333 не реагирует,
но на 12:23:34 возвращает "1" "2" "23:" "3" "34", вот это 23: с двоеточием не очень удобно обрабатывать,
но в целом нормально.

Паттерн "(?:(\d)?(\d):)?(\d)?(\d):(\d+)" - меня в принципе устраивает.
В данный момент другой вопрос больше интересует, как избавиться от цикла?

Чтобы код выглядел примерно так

timestr = "1:10:50 1:28 13:41 14:23:10 2:12 1:44"
regex.Pattern = "(?:(\d)?(\d):)?(\d)?(\d):(\d+)"
Set matches = regex.Execute(timestr)

'А вот тут нужно скорректировать паттерн
timeline = regex.Replace(timestr, "$1|0$2|0:$3|0$4:$5")


Т.е. нужно включить конструкцию ИЛИ, чтобы если $1=="", то оно заменялось на "0",
вот только все способы включить конструкцию ИЛИ у меня не увенчались успехом :(
|0, ||0, \|0

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования