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

时间:2013-03-27 14:20:18

标签: python regex

我想解析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)

因此,请将上面的两个示例保存到变量s1s2中。

这是我写的代码:

>>> 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?我错过了什么?这是贪心 vs 非贪婪问题吗?

3 个答案:

答案 0 :(得分:3)

您希望将.*? 移至可选日期组并使用.search()

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

演示:

>>> RE = r'''
...     (?:(\d) \s day.*?)?        # this should match "n day" if it's there
...     \s(\d{1,2}):(\d{1,2}) # this should match a space followed by "hh:mm"
... '''
>>> print re.search(RE, s1, re.VERBOSE).groups()
('1', '1', '24')
>>> print re.search(RE, s2, re.VERBOSE).groups()
(None, '1', '24')

模式锚定在:上,然后回溯。然后.*?匹配时间签名之前的整个文本,这满足模式。

.*?部分移动到可选的day组(在我的版本中未捕获),您可以保证它不会超越{{1文字文字。

答案 1 :(得分:0)

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

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')

答案 2 :(得分:0)

而不是从命令行读取,另一种方法是直接从/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或拆分内置函数更容易解析