Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python “仅匹配”;特邀艺术家“;在一组文件名中--当前正则表达式太贪婪_Python_Regex - Fatal编程技术网

Python “仅匹配”;特邀艺术家“;在一组文件名中--当前正则表达式太贪婪

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'

我正在用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'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