RegExpProblem 3 mit Chords

  • Jetzt wirds kompliziert:
    Ich will einen Text transponieren, heißt, aus folgendem

    Zitat

    Fm7 Em7 Am G
    Hello Innocence! Though it seams like we've been friends for years.


    soll das hier

    Zitat

    Gbm7 Fm7 Bbm Ab
    Hello Innocence! Though it seams like we've been friends for years.

    werden.
    Es folgt die UDF für mein neues Projekt+Beispiel:

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    ;Schreibweise:
    #cs
    Großbuchstabe A-G
    optional "m" für moll
    optional Zahlen
    optinal "/" & A-G
    #ce
    ;~ $_REGEXP_CHORD="([A-G](#|b){0,1}m{0,1}\d*(/[A-G]){0,1})"
    $_REGEXP_CHORD="\b(?:[A-G](?:#|b)?m?\d*[^\w ]?\b)\b"
    $_TONE_C=0
    $_TONE_Db=1
    $_TONE_D=2
    $_TONE_Eb=3
    $_TONE_E=4
    $_TONE_F=5
    $_TONE_Gb=6
    $_TONE_G=7
    $_TONE_Ab=8
    $_TONE_A=9
    $_TONE_Bb=10
    $_TONE_B=11
    Func _isChord($sChord)
    Return StringRegExp($sChord,$_REGEXP_CHORD,0)
    EndFunc
    Func _ChordTranspose($sChord,$iTones)
    ;$iTones= +- 11
    $firstTone=_ChordGetBasicTone($sChord,0)
    $append=_ChordGetAppendix($sChord)
    $secondTone=Mod($firstTone+$iTones+12,12)
    Return _NumberToLetter($secondTone) & $append
    EndFunc
    Func _ChordGetBasicTone($sChord, $iFlag=0);iFlag: 0=zahl, 1=Buchstabe
    If not _isChord($sChord) Then
    SetError(1);No Chord
    Return
    EndIf
    $matches=StringRegExp($sChord,"^[A-Z](#|b){0,1}",2)
    $sLetter=$matches[0]
    If $iFlag=1 Then Return $sLetter
    Return _LetterToNumber($sLetter)
    EndFunc
    Func _LetterToNumber($sLetter)
    If Not StringRegExp($sLetter,"^[A-Z](#|b){0,1}$",0) Then
    SetError(1);No Letter
    Return
    EndIf
    Switch $sLetter
    Case "C"
    Return 0
    Case "Db","C#"
    Return 1
    Case "D"
    Return 2
    Case "Eb","D#"
    Return 3
    Case "E"
    Return 4
    Case "F"
    Return 5
    Case "Gb","F#"
    Return 6
    Case "G"
    Return 7
    Case "Ab","G#"
    Return 8
    Case "A"
    Return 9
    Case "Bb","A#"
    Return 10
    Case "B"
    Return 11
    EndSwitch
    EndFunc
    Func _NumberToLetter($iNumber)
    If Not isNumber($iNumber) Then
    SetError(1);No Number
    Return
    EndIf
    Switch $iNumber
    Case 0
    Return "C"
    Case 1
    Return "Db"
    Case 2
    Return "D"
    Case 3
    Return "Eb"
    Case 4
    Return "E"
    Case 5
    Return "F"
    Case 6
    Return "Gb"
    Case 7
    Return "G"
    Case 8
    Return "Ab"
    Case 9
    Return "A"
    Case 10
    Return "Bb"
    Case 11
    Return "B"
    EndSwitch
    EndFunc
    Func _ChordGetAppendix($sChord)
    $matches=StringRegExp($sChord,"m{0,1}\d*(/[A-G]){0,1}$",2)
    Return $matches[0]
    EndFunc
    Func _TextTranspose($sText,$iTones)
    $aTmp = StringRegExp($sText,$_REGEXP_CHORD,3)
    For $i=0 To UBound($aTmp)-1
    $tmp=_ChordTranspose($aTmp[$i],1)
    $sText=StringRegExpReplace($sText,$aTmp[$i],$tmp)
    MsgBox(0,"",$sText)
    Next
    Return StringReplace($sText,"q@qq","")
    EndFunc
    Beispiel:
    MsgBox(64,"Funktioniert:Akkordtransponieren",_TransposeChord("Ebm7",-3))
    MsgBox(0,"1"," Fm7 Em7 Am G " & @CRLF & "Hello Innocence! Though it seams like we've been friends for years.")
    MsgBox(0,"2",_TextTranspose(" Fm7 Em7 Am G " & @CRLF & "Hello Innocence! Though it seams like we've been friends for years.",1))

    [/autoit]


    Dummerweise zeigt er so nach dem Transponieren folgendes an:

    Code
    Abbm7      Fm7         Bbm         Ab        
    Hello Innocence! Though it seams like we've been friends for years.

    , da er erst das Fm vorne zum Gbm macht, und am Ende aus dem G ein Ab.
    Wenn ich statt diesem Pattern das hier nehme:

    Code
    "\b(?:[A-G](?:#|b)?m?\d*[^\w ]?\b) "


    zeigt er das:

    Zitat

    Gb F Bb Ab
    Hello Innocence! Though it seams like we've been friends for years.

    , das heißt er lässt hier die zusätzlichen Zeichen wie m oder 7 weg.
    Was kann ich machen, damit er es korrekt transponiert? Ich sehe keinen Ausweg... ;(

    Twitter: @L3viathan2142
    Benutze AutoIt persönlich nicht mehr, da ich keinen Windows-Rechner mehr besitze.

    Einmal editiert, zuletzt von L3viathan2142 (17. Januar 2010 um 14:30)

    • Offizieller Beitrag

    Probier es mal so :

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    ;Schreibweise:
    #cs
    Großbuchstabe A-G
    optional "m" für moll
    optional Zahlen
    optinal "/" & A-G
    #ce
    ;~ $_REGEXP_CHORD="([A-G](#|b){0,1}m{0,1}\d*(/[A-G]){0,1})"
    $_REGEXP_CHORD="\b(?:[A-G](?:#|b)?m?\d*[^\w ]?\b)\b"
    $_TONE_C=0
    $_TONE_Db=1
    $_TONE_D=2
    $_TONE_Eb=3
    $_TONE_E=4
    $_TONE_F=5
    $_TONE_Gb=6
    $_TONE_G=7
    $_TONE_Ab=8
    $_TONE_A=9
    $_TONE_Bb=10
    $_TONE_B=11
    Func _isChord($sChord)
    Return StringRegExp($sChord,$_REGEXP_CHORD,0)
    EndFunc
    Func _ChordTranspose($sChord,$iTones)
    ;$iTones= +- 11
    $firstTone=_ChordGetBasicTone($sChord,0)
    $append=_ChordGetAppendix($sChord)
    $secondTone=Mod($firstTone+$iTones+12,12)
    Return _NumberToLetter($secondTone) & $append
    EndFunc
    Func _ChordGetBasicTone($sChord, $iFlag=0);iFlag: 0=zahl, 1=Buchstabe
    If not _isChord($sChord) Then
    SetError(1);No Chord
    Return
    EndIf
    $matches=StringRegExp($sChord,"^[A-Z](#|b){0,1}",2)
    $sLetter=$matches[0]
    If $iFlag=1 Then Return $sLetter
    Return _LetterToNumber($sLetter)
    EndFunc
    Func _LetterToNumber($sLetter)
    If Not StringRegExp($sLetter,"^[A-Z](#|b){0,1}$",0) Then
    SetError(1);No Letter
    Return
    EndIf
    Switch $sLetter
    Case "C"
    Return 0
    Case "Db","C#"
    Return 1
    Case "D"
    Return 2
    Case "Eb","D#"
    Return 3
    Case "E"
    Return 4
    Case "F"
    Return 5
    Case "Gb","F#"
    Return 6
    Case "G"
    Return 7
    Case "Ab","G#"
    Return 8
    Case "A"
    Return 9
    Case "Bb","A#"
    Return 10
    Case "B"
    Return 11
    EndSwitch
    EndFunc
    Func _NumberToLetter($iNumber)
    If Not isNumber($iNumber) Then
    SetError(1);No Number
    Return
    EndIf
    Switch $iNumber
    Case 0
    Return "C"
    Case 1
    Return "Db"
    Case 2
    Return "D"
    Case 3
    Return "Eb"
    Case 4
    Return "E"
    Case 5
    Return "F"
    Case 6
    Return "Gb"
    Case 7
    Return "G"
    Case 8
    Return "Ab"
    Case 9
    Return "A"
    Case 10
    Return "Bb"
    Case 11
    Return "B"
    EndSwitch
    EndFunc
    Func _ChordGetAppendix($sChord)
    $matches=StringRegExp($sChord,"m{0,1}\d*(/[A-G]){0,1}$",2)
    Return $matches[0]
    EndFunc
    Func _TextTranspose($sText,$iTones)
    $aTmp = StringRegExp($sText,$_REGEXP_CHORD,3)
    For $i=0 To UBound($aTmp)-1
    $tmp=_ChordTranspose($aTmp[$i],1)
    $TempPattern="\b("&$aTmp[$i]&")\b"; Match nur innerhalb der Wortgenze
    $sText=StringRegExpReplace($sText,$TempPattern,$tmp)
    Next
    Return StringReplace($sText,"q@qq","")
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(64,"Funktioniert:Akkordtransponieren",_ChordTranspose("Ebm7",-3))
    MsgBox(0,"1"," Fm7 Em7 Am G " & @CRLF & "Hello Innocence! Though it seams like we've been friends for years.")
    MsgBox(0,"2",_TextTranspose(" Fm7 Em7 Am G " & @CRLF & "Hello Innocence! Though it seams like we've been friends for years.",1))

    [/autoit]