Python中的正则表达式-奇怪的行为

Python中的正则表达式-奇怪的行为,python,regex,Python,Regex,我想分析uptimeUnix命令的输出。 这是两个不同的示例: 14:25 up 1 day, 1:24, 2 users, load averages: 0,56 0,48 0,47 14:25 up 1:24, 2 users, load averages: 0,56 0,48 0,47 (我使用的语言是Python) 因此,假设上面的两个示例保存到变量s1和s2中 这是我写的代码: >>> RE = r''' ((\d) \s day)? #

我想分析
uptime
Unix命令的输出。 这是两个不同的示例:

14:25  up 1 day,  1:24, 2 users, load averages: 0,56 0,48 0,47
14:25  up 1:24, 2 users, load averages: 0,56 0,48 0,47
(我使用的语言是Python)

因此,假设上面的两个示例保存到变量
s1
s2

这是我写的代码:

>>> RE = r'''
    ((\d) \s day)?        # this should match "n day" if it's there 
    .*?                   # this should match everything until the next regex
    \s(\d{1,2}):(\d{1,2}) # this should match a space followed by "hh:mm"
'''

>>> print re.match(RE, s1, re.VERBOSE).groups()
(None, None, '1', '24')
>>> print re.match(RE, s2, re.VERBOSE).groups()
(None, None, '1', '24')

正则表达式的第二部分,即占正常运行时间小时分钟的部分,工作得非常完美。但是为什么元组的第一部分总是
None
?我错过了什么?这是贪婪还是非贪婪的问题?

您想将
*?
移动到可选的日组中,并使用
.search()

演示:

模式锚定在
,然后返回。然后,
*?
匹配时间签名之前的整个文本,这符合模式


通过将
*?
部分移动到可选的
day
组(在我的版本中为非捕获),您可以保证它不会回溯到
day
文字文本。

匹配从字符串的开头开始,添加。*?起初

In [37]: RE=r'.*?((\d) \s day) .*?  \s(\d{1,2}):(\d{1,2})'

In [38]: print re.match(RE, s1, re.VERBOSE).groups()
('1 day', '1', '1', '24')

另一种方法是直接从
/proc/uptime

#!/usr/bin/python

from datetime import timedelta

with open('/proc/uptime', 'r') as f:
    uptime_seconds = float(f.readline().split()[0])
    uptime_string = str(timedelta(seconds = uptime_seconds))

print(uptime_string)
输出:

35 days, 23:06:35.530000

现在,使用tokenise或split内置解析这一点要容易得多

您的正则表达式在n和day之间有三个空格。此外,由于您使用的是match,它只能在字符串的开头找到它。@DavidRobinson:这是一种
re.VERBOSE
模式;空白被忽略。@DavidRobinson Python不将硬编码的空格计算为带有
re.VERBOSE
的空格,您必须对其进行转义。即使在切断空格的时候,它也不起作用。@MartijnPieters,对了,谢谢你的更正。我认为我的第二个观察仍然站得住脚——如果第二个观察是真的话。它不起作用。
search
的行为与这里的
match
完全相同。好的,它起作用了。您是复制并粘贴了控制台的输出还是编写了它?因为元组应该有四个元素长。@whatyouhide:No,我调整了模式以不捕获
day
部分。添加了
*?
trail后返回文本没有意义。它只会重复你已经拥有的,下一组中
1天
1
。我仍然需要对正则表达式充满信心。@whatyouhide:的确,
(?:…)
创建了一个非捕获组;一个只用于逻辑目的的组,而不是用于返回捕获的信息。哦,好吧。非常感谢。我的问题不是关于那个,只是关于正则表达式,但我肯定会尝试一下:)。
#!/usr/bin/python

from datetime import timedelta

with open('/proc/uptime', 'r') as f:
    uptime_seconds = float(f.readline().split()[0])
    uptime_string = str(timedelta(seconds = uptime_seconds))

print(uptime_string)
35 days, 23:06:35.530000