|
|
|
| Приветствую!
В регулярных выражениях я полный нуб, так что прошу элементарной помощи.
Нужно распарсить строку с временами и привести ее к формату "чч:мм:сс"
Строка наподобие такой:
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 :)
Заранее благодарен! | |
|
|
|
|
|
|
|
для: 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";
|
| |
|
|
|
|
|
|
|
для: 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" - для замены
я думаю, что это стандартные методы для регулярных выражений | |
|
|
|
|
|
|
|
для: 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 | |
|
|
|
|
|
|
|
для: heed
(05.02.2010 в 11:43)
| | Спасибо!
Попробую разобраться.
А в VB большая проблема в функциях времени - значения вида мм:сс он воспринимает как чч:мм,
собственно поэтому я и привожу все времена к единому формату | |
|
|
|
|
|
|
|
для: Ptr73
(05.02.2010 в 11:50)
| | >А в VB большая проблема в функциях времени - значения вида мм:сс он воспринимает как чч:мм,
>собственно поэтому я и привожу все времена к единому формату
Именно VB воспринимает? :)
Знаете, если человек на вопрос "что здесь написано?" ответит "12 минут 34 секунды", и на него посмотрят, как на кандидата в дурку - я не удивлюсь. | |
|
|
|
|
|
|
|
для: Trianon
(05.02.2010 в 13:14)
| | Ну как сказать, как сказать.
Я пишу программу для обработки спортивных результатов.
И если окажется, что например биатлонист бежал очередной круг с результатом 12 часов 34 минуты, то тогда на этого биатлониста посмотрят не как на спортсмена, а как на кандидата в дурку :)
Проблема в том, что в VB нельзя явно указать формат используемых временных данных, поэтому при преобразованиях разноформатных времен постоянно возникают проблемы. | |
|
|
|
|
|
|
|
для: Ptr73
(05.02.2010 в 13:26)
| | Всё верно.
Вы работаете в рамках специфического контекста задачи.
И Вам, как программисту, его особенности и приходится реализовывать универсальными [более или менее] инструментами. | |
|
|
|
|
|
|
|
для: 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
|
| |
|
|
|
|
|
|
|
для: Ptr73
(05.02.2010 в 13:43)
| | Для полной точности предлагается
\b(?:(\d)?(\d):)?((\d)?(\d):)?(\d+)
иначе ваш патерн найдет совпадение при 333:333:333
и не найдет "999", хотя это могут быть милесекунды. | |
|
|
|
|
|
|
|
для: 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
(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 | |
|
|
|