RegExReplace Transpose Chords

Get help with using AutoHotkey and its commands and hotkeys
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

RegExReplace Transpose Chords

17 Jun 2018, 00:53

I need a RegExReplace for each below, replace X with Y
This will be the very first X or after "^" or "^^" and before "/" and or "," or none
^^Xm75/X,^^X7m#13/X
^XMb5/X
Xdim7
X,X

This will be the first after the / and before "," if there
^^Xm75/X,^^X7m#13/X
^XMb5/X
Xdim7/X

This will be the very first X after , or after ",^" or ",^^" and before / or none
^^Xm75/X,^^X7m#13/X
^X/X,^^X7m#13/X
Xm75/X,^^X7m#13/X
^^Xm75/X,^X7mb9/X
^Xm75/X,X7m#13/X

This will be the X after "," and "/"
^^Xm75/X,^^X7m#13/X
^X/X,^^X7m#13..sd/X
Xm75/X,^^X7m#13/X
^^Xm75/X,^X7m#13/X
^Xm75/X,X7m#13/X

They are just music chords that will be transposed there are 1 or 2 chords (cut to the Clipboard then transposed and pasted), if there are 2 they are separated by a "," if they are slash chords they will have a note on the end C#m7b5/G so to transpose the first part of the chord only, up I need to change C# to D: Dm7b5/G, if I want to transpose the slash note only, /G to /Ab: C#m7b5/Ab


I hope I have explained it clear enough,
thanks.
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

17 Jun 2018, 15:37

More basic example, just need to be able to replace each X selectively out of the 4 possible.
X/X,X/X
X/X,X
X,X
X,X/X
X/X
X
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

17 Jun 2018, 15:54

- I would suggest showing a list/lists of the form: abc -> def. That way more people will be quicker to help. Cheers.
- You might also list everything that X could be (list/lists).
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

17 Jun 2018, 16:47

So X could be:

C
C#
Db
D
D#
Eb
E
F
F#
Gb
G
G#
Ab
A
A#
Bb
B
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

17 Jun 2018, 16:59

This will probably cover most of the issues:

Code: Select all

;uses: ^ $ [start/end]
;uses: \K
;uses: (?<=) (?<!) (?=) (?!) [positive/negative look-behind/look-ahead assertions]

q:: ;RegEx - replace specific strings
vText := "X/X,X/X"
vOutput := ""
vOutput .= RegExReplace(vText, "^X", "x") "`r`n" ;^ means at the start of the string
vOutput .= RegExReplace(vText, "(?<=/)X(?!$)", "x") "`r`n" ;preceded by a slash, not at the end
vOutput .= RegExReplace(vText, "/\KX(?!$)", "x") "`r`n" ;preceded by a slash, not at the end (alternative)
vOutput .= RegExReplace(vText, "(?<=,)X", "x") "`r`n" ;preceded by a comma
vOutput .= RegExReplace(vText, ",\KX", "x") "`r`n" ;preceded by a comma (alternative)
vOutput .= RegExReplace(vText, "X$", "x") "`r`n" ;$ means at the end of the string
MsgBox, % vOutput
return
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

17 Jun 2018, 17:40

Thanks that works on /X, but some maybe proceeded by ^ or ^^

"X/X,X/X"
"^X/X,X/X"
"^^X/X,X/X"
"X/X,^X/X"
"X/X,^^X/X"
"^^X/X,^^X/X"
"^X/X,^^X/X"
"^X/X,^X/X"
"^X/X,^^X/X"
"^^X/X,^X/X"
"^^X,^X/X"
"^X,^X"
"X,X"
Last edited by MusoCity on 17 Jun 2018, 18:07, edited 1 time in total.
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

17 Jun 2018, 18:03

Probably these:

Code: Select all

;note: ^ indicates starts with
;note: [^a] means not a
;note: \^ indicates ^ (it needs to be escaped with a backslash to use it literally, instead of for a special purpose)
;note: \K can also be used

(?<=^\^) ;starts with ^
(?<=^\^\^) ;starts with ^^
(?<=\^\^) ;preceded by ^^
(?<=[^^]\^) ;preceded by (not ^) and ^
(?<=,\^) ;preceded by ,^
(?<=,\^\^) ;preceded by ,^^
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

17 Jun 2018, 18:19

Finding the first UPPERCASE Letter, might be easier ?
So first UPPERCASE or first UPPERCASE before / or ,
and first UPPERCASE after ,
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

17 Jun 2018, 18:33

- Something like this might help to replace the nth occurrence:

Code: Select all

q:: ;RegEx - replace specific strings
vText := "X/X,X/X"
vOutput := ""
vOutput .= RegExReplace(vText, "X(?=.*X.*X.*X)", "x") "`r`n"
vOutput .= RegExReplace(vText, ".*\KX(?=.*X.*X)", "x") "`r`n"
vOutput .= RegExReplace(vText, ".*\KX(?=.*X)", "x") "`r`n"
vOutput .= RegExReplace(vText, "X(?!.*X)", "x") "`r`n"
MsgBox, % vOutput
return
- There are all sorts of things that can be done. Upper-case letters would be:

Code: Select all

[A-Z]
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

17 Jun 2018, 18:57

Thanks !, that should do the job, I will just try it out on a lot of variations.
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

17 Jun 2018, 20:16

I thought I should mention this, which could be useful at some point:

Code: Select all

[A-G][b#]?
A capital letter between A and G, optionally followed by b or #. The question mark means 0 or 1 of the previous character.
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

17 Jun 2018, 20:58

I just need one RegExReplace for each one of the 4, that will work on any variation of each target.

So there are 4,
1=first chord
2=slash note/ of first chord
3=second chord
4=slash note of second chord

they each need to work no matter what the variation
so
RegExReplace1 will replace only 1 in all the variations
RegExReplace2 will replace only 2 in all the variations
RegExReplace3 will replace only 3 in all the variations
RegExReplace4 will replace only 4 in all the variations

1
^1
^^1
1/2
1/2,3
1/2,3/4
1/2,^3/4
1/2,^^3/4
1,^^3/4
1,^3/4
^1/2,^^3/4
^^1/2,^^3/4
^1,^^3/4
^^1,^^3/4
,3
,3/4
,^3
,^^3
,^^3/4
,^3/4

But don't worry too much I will get the hang of it and work it out.
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

18 Jun 2018, 05:57

These examples seem to be right or mostly right:

Code: Select all

q:: ;RegExReplace - chords
vText := "
(Join`r`n
1
^1
^^1
1/2
1/2,3
1/2,3/4
1/2,^3/4
1/2,^^3/4
1,^^3/4
1,^3/4
^1/2,^^3/4
^^1/2,^^3/4
^1,^^3/4
^^1,^^3/4
 ,3
 ,3/4
 ,^3
 ,^^3
 ,^^3/4
 ,^3/4
)"
vText1 := RegExReplace(vText, "m)^\^*\K\d", "x")
vText1X := RegExReplace(vText, "m)^[^/,\d]*\K\d", "x") ;alternative
;MsgBox, % (vText1 = vText1X)
vText2 := RegExReplace(vText, "m)^[^/,]*/\K\d", "x")
vText3 := RegExReplace(vText, "m)^.*,\^*\K\d", "x")
vText4 := RegExReplace(vText, "m)^.*,.*/\K\d", "x")
Loop, 4
	MsgBox, % vText%A_Index%
return

;1: no slash immediately before it, no comma before it
;2: a slash immediately before it, no comma before it
;3: no slash immediately before it, a comma before it
;4: a slash immediately before it, a comma before it
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

18 Jun 2018, 16:24

Thanks I appreciate all your help, that should do it now hopefully, if you can just convert one of them to a one liner like this
MsgBox, % RegExReplace("C#", "(?<!`,)C#", "D")
without it reading from a list I should be right.

I was reading your tutorial when you came to my rescue, thanks.
jeeswg's RegEx tutorial (RegExMatch, RegExReplace)
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

19 Jun 2018, 22:07

I just can't work out where to put the Needle in that instead of the Multiline

MsgBox, % RegExReplace(Haystack, "m)^\^*\K\d", "Replacement")
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

20 Jun 2018, 04:54

I'm not really sure what you're asking. You could give some input/output examples.
MusoCity
Posts: 29
Joined: 24 Mar 2018, 20:45

Re: RegExReplace Transpose Chords

20 Jun 2018, 16:09

Sorry.
So 1/2,3/4 could be:

C
C# Db
D
D# Eb
E
F
F# Gb
G
G# Ab
A
A# Bb
B
*The # and b are the same note can be named either.
So to transpose C up 1 semitone will be C#
C# or Db up 1 semitone will be D
D up 1 will be D#
etc..
RegExReplace1up will replace the first chord
So say the 1 (the first chord) in this case is C that will be replaced with > C# to transpose the first chord up 1 semitone
1 ( C ) > (C#)
^1 (^C) > (^C#)
^^1 (^^C) > (^^C#)
1/2 (C/G) > (C#/G)
1/2,3 (C/G,C) > (C#/G,C)
1/2,3/4 (C/G,C/A) > (C#/G,C/A)
1/2,^3/4 (Cm7b5/G,^C/A) (C#m7b5/G,^C/A)
1/2,^^3/4 (CMaj7/G,^C/A) (C#Maj7/G,^C/A)
1,^^3/4 (C7b5#9,^^Cm7/G7) > (C#7b5#9,^^Cm7/G7)
1,^3/4 (Caug,^Am/E) > (C#aug,^Am/E)
^1/2,^^3/4 (^Cdim/G,^^Fm/C) > (^C#dim/G,^^Fm/C)

RegExReplace2up will replace the first chord / slash note
So say the 2 (the first chord / slash note) in this case is G that will be replaced with > G# to transpose the first chord / slash note up 1 semitone

1/2 (C/G) > (C/G#)
1/2,3 (C/G,C) > (C/G#,C)
1/2,3/4 (C/G,C/A) > (C/G#,C/A)
1/2,^3/4 (Cm7b5/G,^C/A) > (Cm7b5/G#,^C/A)
1/2,^^3/4 (CMaj7/G,^C/A) > (CMaj7/G#,^C/A)
^1/2,^^3/4 (^Cdim/G,^^Fm/C) > (^Cdim/G#,^^Fm/C)

RegExReplace3up will replace the second chord
So say the 3 (the second chord) in this case is C that will be replaced with > C# to transpose the second chord up 1 semitone

1/2,3/4 (C/G,C/A) > (C/G,C#/A)
1/2,^3/4 (Cm7b5/G,^C/A) > (Cm7b5/G,^C#/A)
1/2,^^3/4 (CMaj7/G,^C/A) > (CMaj7/G,^C#/A)
1,^^3/4 (C7b5#9,^^Cm7/G7) > (C7b5#9,^^C#m7/G7)

RegExReplace4up will replace the second chord / slash note
So say the 4 (the second chord / slash note) in this case is A that will be replaced with > A# to transpose the second chord / slash note up 1 semitone

1/2,3/4 (C/G,C/A) > (C/G,C/A#)
1/2,^3/4 (Cm7b5/G,^C/A) > (Cm7b5/G,^C/A#)
1/2,^^3/4 (CMaj7/G,^^C/A) > (CMaj7/G,^^C/A#)


if that works this :( will be replaced with this :D

What would be handy is something like this http://www.txt2re.com/index.php3 for AHK
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

20 Jun 2018, 16:20

- Thanks for your response, AFAIK you have everything you need. So perhaps, one example of something you're trying to do but haven't managed to do yet.
- I'll see about creating those 4 functions, btw RegExMatch will need to be involved to identify the note to replaced.
- Btw will the text to be replaced literally be one chord, or will other text be present.
swagfag
Posts: 1371
Joined: 11 Jan 2017, 17:59

Re: RegExReplace Transpose Chords

20 Jun 2018, 16:38

Code: Select all

txt =
	(LTrim
		^^Xm75/X,^^X7m#13/X
		^XMb5/X
		Xdim7
		X,X

		^^Xm75/X,^^X7m#13/X
		^XMb5/X
		Xdim7/X

		^^Xm75/X,^^X7m#13/X
		^X/X,^^X7m#13/X
		Xm75/X,^^X7m#13/X
		^^Xm75/X,^X7mb9/X
		^Xm75/X,X7m#13/X

		^^Xm75/X,^^X7m#13/X
		^X/X,^^X7m#13..sd/X
		Xm75/X,^^X7m#13/X
		^^Xm75/X,^X7m#13/X
		^Xm75/X,X7m#13/X
	)

MsgBox, % first(txt, "C#")
MsgBox, % second(txt, "C#")
MsgBox, % third(txt, "C#")
MsgBox, % fourth(txt, "C#")


first(haystack, note) { ;prior to first slash
	return RegExReplace(haystack, "`am)^(\^{0,2})\w(?:b|#)?", "$1" note)
}

second(haystack, note) { ;between first slash and comma
	return RegExReplace(haystack, "`am)(?<=/)\w(?:b|#)?([^,\s]*)(?=,)", note "$1")
}

third(haystack, note) { ;between comma and second slash
	return RegExReplace(haystack, "`am)(?<=,)(\^{0,2})\w(?:b|#)?", "$1" note)
}

fourth(haystack, note) { ;after second slash
	return RegExReplace(haystack, "`am)(?<=/)\w(?:b|#)?([^\s,]*)$", note "$1")
}
User avatar
jeeswg
Posts: 5266
Joined: 19 Dec 2016, 01:58
Location: UK

Re: RegExReplace Transpose Chords

20 Jun 2018, 16:52

This is pretty much what's needed, I've only tested it on a simple chord:

Code: Select all

q:: ;test transpose chords
vText := "A/B,C/D"
MsgBox, % ChordTranspose(vText, 1, 1, 1, 1) ;A#/C,C#/D#
MsgBox, % ChordTranspose(vText, 2, 2, 2, 2) ;B/C#,D/E
MsgBox, % ChordTranspose(vText, -1, -1, -1, -1) ;G#/A#,B/C#
MsgBox, % ChordTranspose(vText, -2, -2, -2, -2) ;G/A,A#/C
return

ChordTranspose(vText, vST1:="", vST2:="", vST3:="", vST4:="", oArray2:="")
{
	static oArray := StrSplit("C,C#,D,D#,E,F,F#,G,G#,A,A#,B", ",")
	static vNeedle1 := "^\^*\K"
	static vNeedle2 := "^[^/,]*/\K"
	static vNeedle3 := "^.*,\^*\K"
	static vNeedle4 := "^.*,.*/\K"
	static number := "number" ;AHK v1/v2 two-way compatibility
	if IsObject(oArray2)
		vArrayName := "oArray2"
	else
		vArrayName := "oArray"

	Loop, 4
	{
		vST := vST%A_Index% ;semitone
		if vST is not number
			continue
		if !vST
			continue
		if !vPos := RegExMatch(vText, vNeedle%A_Index% "[A-G]")
			return
		vNote1 := SubStr(vText, vPos, 2)
		if !RegExMatch(vNote1, "[#b]$")
			vNote1 := SubStr(vNote1, 1, 1)
		for vKey, vValue in %vArrayName%
			if (vValue = vNote1)
			{
				vNum1 := vKey
				break
			}
		if !vNum1
			return
		vNum2 := 1+Mod(vNum1+11+vST%A_Index%, 12)
		if (vNum2 <= 0)
			vNum2 += 12
		vNote2 := %vArrayName%[vNum2]
		vText := RegExReplace(vText, vNeedle%A_Index% vNote1, vNote2)
	}
	return vText
}
Last edited by jeeswg on 20 Jun 2018, 18:33, edited 1 time in total.

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], MannyKSoSo, scriptors, swagfag and 53 guests