Python “仅匹配”;特邀艺术家“;在一组文件名中--当前正则表达式太贪婪
我正在用python编写一个脚本来提取特写艺术家的名字 从mp3文件名开始,并设置文件的相应id3v2标记。文件名有3种不同的格式:Python “仅匹配”;特邀艺术家“;在一组文件名中--当前正则表达式太贪婪,python,regex,Python,Regex,我正在用python编写一个脚本来提取特写艺术家的名字 从mp3文件名开始,并设置文件的相应id3v2标记。文件名有3种不同的格式: Artist - Track ft. FeatArtist.mp3 Artist ft. FeatArtist - Track.mp3 Artist - Track (ft. FeatArtist).mp3 这是我写的正则表达式: r'ft\. (.+)[.-)]' 然后我可以使用re.findall获取组的内容。但我得到的是: In [40]: r = r'
Artist - Track ft. FeatArtist.mp3
Artist ft. FeatArtist - Track.mp3
Artist - Track (ft. FeatArtist).mp3
这是我写的正则表达式:
r'ft\. (.+)[.-)]'
然后我可以使用re.findall
获取组的内容。但我得到的是:
In [40]: r = r'ft\. (.+)[.\-)]'
In [47]: re.findall(r, 'Artist - Track ft. FeatArtist.mp3')
Out[47]: ['FeatArtist']
In [48]: re.findall(r, 'Artist ft. FeatArtist - Track.mp3')
Out[48]: ['FeatArtist - Track']
In [49]: re.findall(r, 'Artist - Track (ft. FeatArtist).mp3')
Out[49]: ['FeatArtist)']
我的预期输出在所有三种情况下都是准确的:
FeatArtist
问题是正则表达式正在尽可能多地匹配-我希望它在[.\-)]
中找到一个字符后立即停止。我如何才能做到这一点?这应该可以:
(?<=ft\. )[^\-)\. ]+
(?用于python)
根据文件名格式的具体要求:
每个文件名:
事情可能会分崩离析。解决上述问题的一种方法可能是:
首先,在根本不使用字符串匹配的情况下删除文件扩展名。使用文件名执行此操作可以为您提供一个更清晰的起点:
使用os.path.splitext('Artist-Track ft.FeatArtist.mp3')[0])
可以获得以下格式的文件:Artist-Track ft.FeatArtist
我们可以使用此正则表达式容纳新文件名:
-
结果:
为什么不回头看?
从python人(添加了格式):
re.findall(模式、字符串、标志=0)
返回字符串中模式的所有非重叠匹配项,作为字符串列表。从左到右扫描字符串,并按找到的顺序返回匹配项如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。空匹配将包含在结果中,除非它们触及另一个匹配的开头
因此,您仍然可以使用reption操作符来建立匹配,并使用组来控制返回的匹配部分
做类似事情的其他方法:
如果使用支持\K
反向引用的正则表达式引擎,则匹配将是\K
后面的所有内容:
使用grep
与-p
(Perl Regex)和-o
(仅返回匹配项)的示例:
嗯?一个字符类只匹配一个字符。“贪婪”和“非贪婪”在这种情况下没有真正的意义。它根本不是一个完全相同的@WiktorStribiżewI事实上非常赞同在问题更新为完全明确之前结束问题(或逐字回答但毫无帮助)的论点。我的回答解决了OP给出的字面问题,消除了贪婪;他们没有提供样本输出,说他们想要Feat.Artist
而不是Feat
,他们确实说他们想要一个非贪婪的匹配,所以Feat
正是用贪婪匹配代替非贪婪匹配所提供的。他们还想要别的吗?“他们有责任问一个更好的问题。”查理·达菲在法庭上说,你会轻而易举地赢得这场辩论。两个拥有超过10万代表的管理员,我甚至连停车场的空间都没有。但是从样本输出和3种类型输入文件的明确规范以及它的用途来看,很明显(或者至少是基于信息的合理的最佳情况),Feat
不会削减它。当然。但是StackOverflow从创立到现在的目的并不是帮助一对一提问的人——它是而且一直是建立一个长尾知识库;一对一地帮助人们是我们朝着更大目标所做的事情。这意味着写问题不仅要帮助第一个问问题的人,还要帮助通过搜索等方式在谷歌上找到问题的其他人。;如果有人通过谷歌找到了如何使搜索不贪婪的答案,那么一个偏离正切的答案不太可能有帮助。我认为应该是“[^-。]+,而不是“
[^-。]+>”,因为在某些情况下,艺术家的名字可能会有空格。非常感谢你的回答:)@Gokul是的。也就是说,如果我是你,我会通过编程检查字符串,并删除末尾的空白,因为不带空格的正则表达式可以生成类似artist
的字符串,当与artist
(末尾没有空格)比较时,将返回false。我接受了hmedia1答案,因为它更广泛,可能对其他寻求解决方案的人更有用。但是你的回答很好;谢谢你
re.findall(r'ft\.\s*(\w*)',filename)
Artist - Track ft. FeatArtist.mp3
Artist ft. FeatArtist - Track.mp3
Artist - Track (ft. FeatArtist).mp3
['FeatArtist']
Feat.Artist
Feat Artist
Feat Middlename Artist
Feat Artist One & Artist Two
re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)', filename)
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist - Track ft. FeatArtist')
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist ft. FeatArtist - Track')
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist - Track (ft. FeatArtist)')
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist - Track (ft. Feat Artist)')
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist - Track (ft. Feat Artist & Other Artist)')
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist ft. Feat Artist & Other Artist - Track')
>>> re.findall(r'ft\.\s*(\w*.*?)(?= -|\)|$)','Artist ft. Feat.Artist & Crew - Track')
['FeatArtist']
['FeatArtist']
['FeatArtist']
['Feat Artist']
['Feat Artist & Other Artist']
['Feat Artist & Other Artist']
['Feat.Artist & Crew']
echo "Artist - Track ft. FeatArtist" | grep -oP "ft\.\s*\K(\w*.*?)(?= -|\)|$)"
FeatArtist
echo "Artist ft. FeatArtist - Track" | grep -oP "ft\.\s*\K(\w*.*?)(?= -|\)|$)"
FeatArtist
echo "Artist - Track (ft. FeatArtist)" | grep -oP "ft\.\s*\K(\w*.*?)(?= -|\)|$)"
FeatArtist
echo "Artist ft. Feat Artist & Other Artist - Track" | grep -oP "ft\.\s*\K(\w*.*?)(?= -|\)|$)"
Feat Artist & Other Artist