Reputation: 19
I need to write a regular expression to find time markers in the video from a string. For example, I have this:
00:00 - вступление Сергея Немчинского
01:26 - профессия это не на всю жизнь
04:45 - важность выбора языка программирования
07:48 - системы управления контролем версий
09:51 - поисковик
12:10 - больше практики
13:12 - и больше отдыха
14:38 - программирование это больше чем синтаксис
17:15 - невозможно выучить все
10:19:38 - разберитесь в себе и делайте то, что нравится :)
I need to extract [00:00, 01:26, 04:45, etc.]
I have this (?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$
But it doesen't works properly.
Upvotes: 1
Views: 107
Reputation: 163577
Your pattern contains optional capture groups for the first 2 parts. That way it will also match for example just 10
You can omit the anhor $
at the end, and add an anchor ^
at the start.
Then only make the last group optional as the last value in the example data 10:19:38
consists of 3 parts.
^(?:[01]?\d|2[0-3]):[0-5]?\d(?::[0-5]?\d)?\b
The pattern matches:
^
Start of string(?:[01]?\d|2[0-3])
Match from 00 to 19 or 20 to 23:[0-5]?\d
Match from 00 to 59(?::[0-5]?\d)?
Optionally match from 00 to 59\b
A word boundary to prevent a partial matchExample
import re
pattern = r"^(?:[01]?\d|2[0-3]):[0-5]?\d(?::[0-5]?\d)?\b"
s = ("00:00 - вступление Сергея Немчинского\n"
"01:26 - профессия это не на всю жизнь\n"
"04:45 - важность выбора языка программирования\n"
"07:48 - системы управления контролем версий\n"
"09:51 - поисковик\n"
"12:10 - больше практики\n"
"13:12 - и больше отдыха\n"
"14:38 - программирование это больше чем синтаксис\n"
"17:15 - невозможно выучить все\n"
"10:19:38 - разберитесь в себе и делайте то, что нравится :)\n")
print(re.findall(pattern, s, re.MULTILINE))
Output
['00:00', '01:26', '04:45', '07:48', '09:51', '12:10', '13:12', '14:38', '17:15', '10:19:38']
Upvotes: 1
Reputation: 4674
Assuming the following:
00:00
, 00:00:00
, or 00:00:00.00
Then:
s = '''
00:00 - вступление Сергея Немчинского
01:26 - профессия это не на всю жизнь
04:45 - важность выбора языка программирования
07:48 - системы управления контролем версий
09:51 - поисковик
12:10 - больше практики
13:12 - и больше отдыха
14:38 - программирование это больше чем синтаксис
17:15 - невозможно выучить все
10:19:38 - разберитесь в себе и делайте то, что нравится :)
'''
# extract times as tuples of strings [('', '00', '00'), ('', '01, '26'), ...]
times = re.findall(r'^(?:(\d\d):)?(\d\d):(\d\d(?:\.\d*)?)', s, re.M)
# convert to integers and floats [(0, 0, 0.0), (0, 1, 26.0), ...]
times = [(int(h or 0), int(m), float(s or 0)) for h, m, s in times]
# convert to timedeltas [timedelta(0), timedelta(0, 86), ...]
times = [datetime.timedelta(hours=h, minutes=m, seconds=s) for h, m, s in times]
# results
for time in times:
print(time)
0:00:00
0:01:26
0:04:45
0:07:48
0:09:51
0:12:10
0:13:12
0:14:38
0:17:15
10:19:38
The regex has these parts:
^
must start at beginning of line(?:(\d\d):)
optional hour part like 00:
(\d\d):
required minute part like 00:
(\d\d(?:\.\d*)?)
required second part with optional decimal like 00
or 00.00
Each number is grouped with ()
so that findall
will return one string-number-per-element tuples.
The pattern int(h or 0)
is used because the regex can return ''
which isn't a valid int
, but '' or 0
becomes 0
which is a valid int
.
Upvotes: 0
Reputation: 9047
s = '''00:00 - вступление Сергея Немчинского
01:26 - профессия это не на всю жизнь
04:45 - важность выбора языка программирования
07:48 - системы управления контролем версий
09:51 - поисковик
12:10 - больше практики
13:12 - и больше отдыха
14:38 - программирование это больше чем синтаксис
17:15 - невозможно выучить все
10:19:38 - разберитесь в себе и делайте то, что нравится :)'''
import re
re.findall(r'^\d[\d:]+', s, re.MULTILINE)
# ['00:00',
# '01:26',
# '04:45',
# '07:48',
# '09:51',
# '12:10',
# '13:12',
# '14:38',
# '17:15',
# '10:19:38']
Description of the regex here
Upvotes: 2