【发布时间】:2013-09-07 11:45:56
【问题描述】:
我对解析各种格式的曲目列表感兴趣,其中包含以下行:
artist - title
artist-title
artist / title
artist - "title"
1. artist - title
0:00 - artist - tit le
05 artist - title 12:20
artist - title [record label]
这些是文本文件,通常包含一个曲目列表,但也可能包含我不想解析的其他内容,因此理想情况下,正则表达式需要足够严格,以不包含不是曲目列表的行,尽管确实如此可能是平衡的问题。
我在以下正则表达式方面取得了一些成功:
simple = re.compile(r"""
^
(?P<time>\d?\d:\d\d)? # track time in 00:00 or 0:00
(
(?P<number>\d{1,2}) # track number as 0 01
[^\w] # not followed by word
)?
[-.)]? # possibly followed by something
"?
(?P<artist>[^"@#]+) # artist anything except "@#
"?
\s[-/\u2013]\s
"? # dash surrounded by spaces, possibly unicode
(?P<title>[^"@#]+?) # title, not greedy
"?
(?P<label>\[\w+\])? # label i.e. [something Records]
(//|&\#13;)? # remove some weird endings, i.e. ascii carriage return
$
""", re.VERBOSE)
但是,这有点可怕,我最近才开始学习正则表达式。像这样的行有问题:
an artist-a title # couldn't find ' - '
2 Croozin' - 2 Pumpin' # mistakes 2 as track number
05 artist - title 12:20 # doesn't work at all
在 2 Croozin' - 2 Pumpin' 的情况下,判断 2 不是曲目编号的唯一方法是考虑周围环境,即查看其他曲目。 (我忘了提到这一点 - 这些曲目通常是曲目列表的一部分)
所以我的问题是,我一般如何改进这一点?我的一些想法是:
- 使用多个正则表达式,从非常具体的开始,然后继续使用不太具体的正则表达式,直到正确解析为止。
- 转储正则表达式并使用适当的解析器,例如 pyparsing 或 parsley,这可能能够更好地利用周围的上下文,但是我对解析一无所知
- 在多行正则表达式中使用前瞻/后瞻来查看上一行/下一行
- 使用单独的正则表达式获取时间、曲目编号、艺术家、标题
- 放弃并做一些没有意义的事情
我可以验证它已正确解析(在某种程度上)做一些事情,例如确保艺术家和标题都不同、曲目有序、时间合理,甚至可能检查艺术家/标题/标签确实存在.
【问题讨论】:
-
你不会碰巧有一堆 mp3 或类似的,上面有适当的元数据吗?或者,您是否真的在尝试处理文本文件和行列表或其他东西......
-
由于您的语法固有的歧义,您将不得不尝试解析许多不同的方式并检查每种方式是否“有意义”(您提到您能够在某种程度上进行验证.) 然后您可以选择第一个有意义的解析,或者您可以根据它们的常见程度为解析分配权重,然后选择也有意义的“最佳”解析。我不认为将所有内容都塞进一个正则表达式中会起作用。您必须使用某种标记化然后进行解析。 (尽管如果您愿意,可以使用正则表达式进行标记化。)
-
@JonClements:感谢您的提问,我意识到我没有提供足够的上下文并更新了问题
-
@kqr:你对解析了解很多吗?你能推荐一些资源来帮助我解决这个特殊问题吗?
标签: python regex parsing text-parsing pyparsing