【问题标题】:python regex for repeating string用于重复字符串的python正则表达式
【发布时间】:2011-06-06 19:35:45
【问题描述】:

我想验证然后解析这个字符串(用引号引起来):

string = "start: c12354, c3456, 34526; other stuff that I don't care about"
//Note that some codes begin with 'c'

我想验证字符串是否以 'start:' 开头并以 ';' 结尾 之后,我想让一个正则表达式解析出字符串。我尝试了以下python重新代码:

regx = r"start: (c?[0-9]+,?)+;" 
reg = re.compile(regx)
matched = reg.search(string)
print ' matched.groups()', matched.groups()

我尝试了不同的变体,但我可以得到第一个或最后一个代码,但不是所有三个的列表。

或者我应该放弃使用正则表达式吗?

编辑:更新以反映我忽略的部分问题空间并修复了字符串差异。 感谢所有建议 - 在这么短的时间内。

【问题讨论】:

  • 缩进代码 4 个空格或使用帖子编辑器中的“{}”按钮。我为你修好了。顺便说一句,您的意思是“V1 OID”还是“开始”?

标签: python regex parsing


【解决方案1】:

在 Python 中,使用单个正则表达式无法做到这一点:组的每次捕获都会覆盖同一组的最后一次捕获(在 .NET 中,这实际上是可能的,因为引擎会区分捕获和组)。

您最简单的解决方案是首先提取start:;之间的部分,然后使用正则表达式返回所有匹配项,而不仅仅是单个匹配项,使用re.findall('c?[0-9]+', text)

【讨论】:

  • 对我来说很合适。你也可以看看这个。但是您可以使用正则表达式来查找开始:和;并执行两步过程。你可能想看看这个。 stackoverflow.com/questions/1099178/…
  • 谢谢,我想知道正则表达式组和单个正则表达式 search() 调用的重复。我也改用了 findall() 但我在这里问这个问题只是想看看是否有更好的方法。
【解决方案2】:

您可以使用标准的字符串工具,它们几乎总是更具可读性。

s = "start: c12354, c3456, 34526;"

s.startswith("start:") # returns a boolean if it starts with this string

s.endswith(";") # returns a boolean if it ends with this string

s[6:-1].split(', ') # will give you a list of tokens separated by the string ", "

【讨论】:

  • 是的,我知道我可以使用直接字符串解析,但是我必须编写代码来验证字符串格式,而不是使用正则表达式,你可以立即获得。
【解决方案3】:

这可以使用Pyparsing 之类的工具来完成(非常优雅):

from pyparsing import Group, Literal, Optional, Word
import string

code = Group(Optional(Literal("c"), default='') + Word(string.digits) + Optional(Literal(","), default=''))
parser = Literal("start:") + OneOrMore(code) + Literal(";")
# Read lines from file:
with open('lines.txt', 'r') as f:
    for line in f:
        try:
            result = parser.parseString(line)
            codes = [c[1] for c in result[1:-1]]
            # Do something with teh codez...
        except ParseException exc:
            # Oh noes: string doesn't match!
            continue

比正则表达式更简洁,返回代码列表(无需string.split),并忽略行中的任何额外字符,就像您的示例一样。

【讨论】:

  • 感谢您提供 pyparsing 解决方案!需要考虑的其他一些选项:将代码定义为Word('c'+string.digits, string.digits);那么解析器可以是'start:' + delimitedList(code)("codes") + ';';代码列表可以通过codes = result.codes这样的结果名称访问——一般来说,我会尽可能保持代码之类的定义干净,而不是与可选的逗号分隔符之类的东西混淆;而是在解析器组合的下一个更高级别添加逗号。但是你的解析器肯定能完成工作——恭喜!
  • @Paul:太好了!以前不知道delimitedListLiteral 是可选的完全有道理。好东西...谢谢!
  • 有趣。我将不得不研究 pyparsing。感谢您的帖子。
【解决方案4】:
import re

sstr = re.compile(r'start:([^;]*);')
slst = re.compile(r'(?:c?)(\d+)')

mystr = "start: c12354, c3456, 34526; other stuff that I don't care about"
match = re.match(sstr, mystr)
if match:
    res = re.findall(slst, match.group(0))

结果

['12354', '3456', '34526']

【讨论】:

  • 感谢您编写 madmik3 建议的答案 - 非常有帮助。
猜你喜欢
  • 2015-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多