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