【问题标题】:Python regex - extracting directories from pathPython regex - 从路径中提取目录
【发布时间】:2012-03-05 08:12:20
【问题描述】:

我有一个关于正则表达式/Python 的问题。抱歉,如果这个话题已经被讨论了数百万次 - 通常我会在 so/google 等上找到答案,但我被这个问题困在数百万个答案中。(说实话 - 我拥有一本正则表达式书,但不知何故我太笨了,根本看不懂……)

对于音乐管理系统,我需要从路径中提取信息,提供不同的选项集。这里举两个例子:

如果路径是:(案例1)

"/The Prodigy/The Fat Of The Land/04 - Funky Stuff.flac"
它应该提取:
  • 艺术家:“神童”
  • 发布:“大地之肥”
  • 曲目编号:4
  • 标题:“时髦的东西”

例如:(案例2)

"/[XLR 483] The Fat Of The Land/04 - The Prodigy - The  Funky Stuff.flac"
应该提取:
  • 目录号:“XLR 483”
  • 发布:“大地之肥”
  • 曲目编号:4
  • 艺术家:“神童”
  • 标题:“时髦的东西”

不需要涵盖这两种情况的正则表达式,这只是两个示例。然后,我会将它们作为选项(或添加自己的选项的起点)提供。

任何帮助将不胜感激!

@S.Lott:我没有正则表达式,我从拆分字符串开始:

parts = rel_path.split('/')       
track = parts[-1]
release = parts[-2]
artist = parts[-3]

但这对我来说似乎是一个非常不灵活且不优雅的解决方案。

编辑:

到目前为止,我有类似的东西:

pattern = re.compile('^/(?P<artist>[a-zA-Z0-9 ]+)/(?P<release>[a-zA-Z0-9 ]+)/(?P<track>[a-zA-Z0-9 -_]+).[a-zA-Z]*.*')


rel_path = '/The Prodigy/The Fat Of The Land/04 - Funky Stuff.flac'

match = pattern.search(rel_path)

artist = match.group('artist')
release = match.group('release')
track = match.group('track')

【问题讨论】:

  • 第 1 步。发布您正在使用的正则表达式以及您遇到的问题。我们可以提供帮助,但我们不喜欢为您编写代码。发布正则表达式以及每个正则表达式出了什么问题。
  • 分割字符串有什么问题?它有效,对吧?
  • @ S.Lott - 拆分没有错,但是很难让模式可编辑(在代码之外)。我想在管理界面中提供(可编辑的)预设。
  • a-zA-Z??你为什么不使用 Unicode?​​span>
  • 如上所述 - 可能是因为我不够聪明,无法理解它...... :)

标签: python regex path extraction


【解决方案1】:

这是我解决您遇到的问题的方法。

  1. 分割路径,检查它是 len 4(第一种情况)还是 3(第二种情况)。
  2. 忽略应该是单个“/”的第一个元素,对于第二个元素,对其进行操作以提取 [xxx]。
  3. 在最后一个元素上用“-”分割以获取您的其他信息。

如果您有任何具体疑问,请在编写正则表达式时编辑您的问题并遵循 S.Lott 的建议。

【讨论】:

  • 好的。 Thx - 拆分有效,但很难在管理界面中进行编辑,因为逻辑完全位于代码中。本来也是我的第一种方法:),但正在寻找更模块化的解决方案。
【解决方案2】:
pattern1 = re.compile(r'/([^/]*)/([^/]*)/([0-9]*) - (.*)\.[^.]*')
artist,release,Tracknumber,Title = pattern1.match(file1).groups()

pattern2 = re.compile(r'/\[([^]]*)\] ([^/]*)/([0-9]*) - (.*) - (.*)\.[^.]*')
catno,release,Tracknumber,artist,Title = pattern2.match(file2).groups()

(其中file1file2 是您在上面给出的路径)。

第一件事:你捕捉到的东西与带有括号的正则表达式匹配。因此,下面括号之间的所有内容都将作为匹配项返回。

第二:你可以匹配除正斜杠以外的任何东西,比如[^/]。所以要在正斜杠之间匹配很多东西,你可以使用[^/]*

把这些放在一起,在你的第一个字符串中捕捉艺术家,你做/([^/]*)/。然后你再次这样做以获得版本。

第三:要匹配任何数字,请使用[0-9]。因此,要匹配任何数字字符串,请使用 [0-9]*

反复应用这些原则,您应该能够理解以上内容。

【讨论】:

  • 谢谢,是的,这有帮助。不知道可以这样直接分配groups()!
  • 是的。 groups() 只返回一个元组,这是为元组的不同部分分配单个名称的一般方法。
【解决方案3】:

您应该首先使用split/ 分隔符,这样您就可以仅使用split 返回的数组大小来获取信息。

然后您可以根据需要使用正则表达式。例如,在第二种情况下:(只有当你有两个元素时才会发生这种情况?)

import re
item = "/[XLR 483] The Fat Of The Land/04 - The Prodigy - The  Funky Stuff.flac"
matches = re.search('^\/?\[([^\]]+)](.*)\/', item)
print matches.group(1) # 'XLR 483'
print matches.group(2) # ' The Fat Of The Land'

可能看起来有点复杂,但是我已经把所有的模棱两可的字符都转义了,所以基本上,模式如下:

  1. ^开头
  2. /? 最多可以有一个斜线 / 后跟...
  3. [ 大括号
  4. ([^\]]+) 包含一次或多次 +(请使用分组括号捕获值)和
  5. ] 一个右花括号,后跟
  6. (.*) 不是通过括号捕获的换行符(0 次或多次 *
  7. 和尾部斜杠/

希望这会有所帮助!

【讨论】:

  • 是的——我之前一直这样......但是如何让它足够模块化以将它分配给变量 - 这样就可以恢复目录......
【解决方案4】:

虽然不是必须的,但是 re 是解决这个问题的方便选择。

import re
pattern = re.compile(r"/(?P<artist>[a-zA-Z0-9 ]+?)/(?P<release>[a-zA-Z0-9 ]+?)/(?P<tracknumber>\d+?) - (?P<title>[a-zA-Z0-9 ]+?).flac")
s = "/The Prodigy/The Fat Of The Land/04 - Funky Stuff.flac"
m = pattern.search(s)
print m.group('artist')
print m.group('release')
print m.group('track number')
print m.group('title')

我使用诸如[a-zA-Z0-9 ] 之类的表达式来明确指定字符串中我期望的字符。我更喜欢使用类似白名单的正则表达式来使代码更安全。还有许多其他方法可以组成等效模式。你会在这里找到所有你需要的东西http://docs.python.org/library/re.html,你不需要一本书。

【讨论】:

  • ?这究竟是如何工作的?不明白这个,但看起来很神奇!
猜你喜欢
  • 2011-09-24
  • 2014-03-07
  • 2011-09-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 2011-12-11
  • 1970-01-01
相关资源
最近更新 更多