我需要帮助编写用于检测和弦的正则表达式

时间:2012-12-25 13:38:22

标签: python regex

我正在写一个文本到cdr(chordpro)转换器,我在检测表单上的和弦线时遇到问题:

               Cmaj7    F#m           C7    
Xxx xxxxxx xxx xxxxx xx x xxxxxxxxxxx xxx 

这是我的python代码:

def getChordMatches(line):
    import re
    notes = "[CDEFGAB]";
    accidentals = "(#|##|b|bb)?";
    chords = "(maj|min|m|sus|aug|dim)?";
    additions = "[0-9]?"
    return re.findall(notes + accidentals + chords + additions, line)

我希望它返回一个列表[“Cmaj7”,“F#m”,“C7”]。上面的代码不起作用,我一直在努力与文档,但我没有得到任何地方。

为什么将类和组链接在一起不起作用?

修改

谢谢,我最终得到了以下内容,其中涵盖了我的需求(例如,它不符合E#m11)。

def getChordMatches(line):
    import re

    notes = "[ABCDEFG]";
    accidentals = "(?:#|##|b|bb)?";
    chords = "(?:maj|min|m|sus|aug|dim)?"
    additions = "[0-9]?"
    chordFormPattern = notes + accidentals + chords + additions
    fullPattern = chordFormPattern + "(?:/%s)?\s" % (notes + accidentals)
    matches = [x.replace(' ', '').replace('\n', '') for x in re.findall(fullPattern, line)]
    positions = [x.start() for x in re.finditer(fullPattern, line)]

    return matches, positions

3 个答案:

答案 0 :(得分:3)

您应该通过将(...)更改为(?:...)来使您的群组无法捕获。

accidentals = "(?:#|##|b|bb)?";
chords = "(?:maj|min|m|sus|aug|dim)?";

查看在线工作:ideone


当你拥有捕获组时它不起作用的原因是它只返回那些组而不是整个匹配。来自文档:

  

<强> re.findall(pattern, string, flags=0)

     

返回字符串中pattern的所有非重叠匹配,作为字符串列表。从左到右扫描字符串,并按找到的顺序返回匹配项。 如果模式中存在一个或多个组,则返回组列表;如果模式有多个组,这将是一个元组列表。结果中包含空匹配,除非它们触及另一场比赛的开头。

答案 1 :(得分:3)

编写详细的正则表达式

有一种特定的语法
regex = re.compile(
    r"""[CDEFGAB]                 # Notes
        (?:#|##|b|bb)?            # Accidentals
        (?:maj|min|m|sus|aug|dim) # Chords
        [0-9]?                    # Additions
     """, re.VERBOSE
)
result_list = regex.findall(line)

它可以说比加入字符串更清晰

答案 2 :(得分:2)

您需要使群组无法捕捉:

def getChordMatches(line):
    import re
    notes = "[CDEFGAB]";
    accidentals = "(?:#|##|b|bb)?";
    chords = "(?:maj|min|m|sus|aug|dim)?";
    additions = "[0-9]?"
    return re.findall(notes + accidentals + chords + additions, line)

结果:

['Cmaj7', 'F#m', 'C7']