Jag skulle vilja ha hjälp med ett mönster(patton).
Den skall hitta allt inom () t ex ( Am7). Hur bör ett sådant mönster se ut?
Regex problem
18 svar · 1 085 visningar · startad av saw
\(*\)
Nja det lyckades inte riktigt.
När jag försöker med
(*.?)
ERROR
parsar (*.?) - Kvantifieraren {x,y} följer på ingenting.
När jag försökte med
\\(*\\)
så visade den enbart ).
Kanske jag inte har skrivit min kod ordentligt?
string kollaM = "\\(*\\)";
Regex repost = new Regex(kollaM,RegexOptions.IgnoreCase|RegexOptions.Compiled);
Match m;
m = repost.Match(richTextBoxEx1.Text);
if (m.Success)
{
richTextBoxEx1.SelectionStart = m.Index;
richTextBoxEx1.SelectionLength = m.Length;
label6.Text = m.Value.ToString();
}
Ser min kod mysko ut?
\(*\)
Denna kommer bara träffa:
()
(()
((() osv.
\(.*\)
. = vilket tecken som helst, * mellan 0 till hur många gånger som hellst (så många gånger som möjligt).
Nu börjadet att hända någonting men jag får med mig parentesen (G7m).
Jag skulle alltså vilja ha G7m.
RegExp:
\((.*)\)
För att lägga in träffen i en grupp och använd
m.Groups[1].ToString()
för att få ut G7m (tror jag)
Nu är vi på rätt väg, men ett problem (vad jag är ute efter är att få ackorden att ljuda).
Om det bara finns ett ackord (Gm7) då är det inga problem, men om det finns flera då
läser scriptet in det som ( (G) (C) (F) (C) )
Jag borde väll kunna ha en foreach slinga eller något?
try {
Regex regexObj = new Regex(@"\((.*)\)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Multiline);
Match matchResults = regexObj.Match(richTextBoxEx1.Text);
while (matchResults.Success) {
label6.Text += matchResults.Groups[1].Value;
matchResults = matchResults.NextMatch();
}
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}
Om Du har en text som ser ut:
"(G) (C) (F) (C)"
Om du har en "grupp":
( (G) (C) (F) (C) )
Så kommer den retunera " (G) (C) (F) (C) "
Frågan är lite mer: Vilka tecken är godkända att ha mellan () ?(blåbär) skall den träffa den, skall den träffa mellanslag osv?
voigtann1 skrev:
\(*\)Denna kommer bara träffa:
()
(()
((() osv.\(.*\). = vilket tecken som helst, * mellan 0 till hur många gånger som hellst (så många gånger som möjligt).
Tack, jag var visst lite snabb!
Tack för att du försöker att hjälpa mig.
Först
Match matchResults = regexObj.Match(richTextBoxEx1.SelectedText);
[/kod
..det måste vara så eftersom det är markerad text det är tal om.
Sen hur den skall leta, tänkt dig så här:
Blinka lilla stjärna där
(C) (F) (C)
hur jag undrar var du är..
(F) (C) (G7) (C)
Med andra ord så kan hela eller dela av dokumentet markeras.
Därefter så kommer..
[kod]
resultat = m.Groups[1].ToString();
string sUtakat = "inget";
string sAckord = "";
if (resultat.Contains("#"))
{
sAckord = resultat.Substring(0, 2);
sUtakat = resultat.Substring(2);
}
else
{
sAckord = resultat.Substring(0, 1);
sUtakat = resultat.Substring(1);
}
if (sUtakat.Length == 0)
sUtakat = "inget";
PlayAckord(sAckord, sUtakat);
Detta innebär ju att jag måste ha ackorden "en efter en".
Jag har haft detta fungerande tidigare, men jag fich en crach och jag minns
tyvärr inte hur jag gjorde. :l
Så när du har markerat
Blinka lilla stjärna där
(C) (F) (C)
hur jag undrar var du är..
(F) (C) (G7) (C)
Så skall resultatet bli:
CFCFCG7C?
Alldeles korrekt.
Eller så här
C
F
C ...
dvs att detta borde nog ligga i en loop där ett ackord i sänder kommer fram.
Vad sägs om att läsa dokumentationen lite? :) För att få fram alla sekvenser som matchar en regexp använder man Regex.Matches(string):
string subject =
"Blinka lilla stjärna där" +
"(C) (F) (C)" +
"hur jag undrar var du är.." +
"(F) (C) (G7) (C)";
Regex re = new Regex(@"\((.*?)\)");
foreach (Match match in re.Matches(subject))
{
Console.WriteLine(match.Groups[1]);
}
ger
C
F
C
F
C
G7
C
red. *? är bättre för oss eftersom * är greedy, dvs den försöker matcha så mycket som möjligt. Eftersom "." matchar allt förutom radbrytningar, matchar den även högerparantes, vilket innebär att "\(.*\)" effektivt betyder "allt fr.o.m. första vänsterparantesen t.o.m. sista högerparantesen på varje rad". Använder man *? istället försöker regexpen matcha så lite som möjligt, vilket innebär att "\(.*?\)" betyder "allt från och med varje vänsterparantes t.o.m. nästa högerparantes". Lägger man sedan till så att det blir "\((.*?)\)" får vi en capturing group på innehållet mellan paranteserna, så att vi direkt kan hämta ut det med match.Groups[1].
Ännu bättre med något som bara plockar fram giltiga ackord, typ
\(([a-hA-H])(#?)(\d?)\)
dvs, först en ton, eventuellt följt av ett kors, eventuellt följt oktavnummer, alla i varsin capture group. Går förstås att göra ännu bättre valideringar, exempelvis finns väl inte B# eftersom det blir C.
Tack nu har jag någonting att fortsätta med.
[REDIGERAT]
Nej tyvärr det fungerar inte som jag hadde tänkt. Jag försöker att läsa och
leta men jag hittar ingenting som hjälper mig, därför så fortsätter jag med
denna tråden.
Så här ser nu koden ut:
string resultat = "";
string sUtakat = "inget";
string sAckord = "";
string subject = richTextBoxEx1.SelectedText;
Regex re = new Regex(@"\(([^\)]+)\)");
foreach (Match match in re.Matches(subject))
{
resultat = match.Groups[1].ToString();
if (resultat.Contains("#"))
{
sAckord = resultat.Substring(0, 2);
sUtakat = resultat.Substring(2);
}
else
{
sAckord = resultat.Substring(0, 1);
sUtakat = resultat.Substring(1);
}
if (sUtakat.Length == 0)
sUtakat = "inget";
PlayAckord(sAckord, sUtakat);
label6.Text = match.Groups[1].ToString();
}
Problemet är att scriptet läser alla ackorden med en gång, jag är mera inne
på en loop så att ackorden säses av ett efter ett, och spelas ett efter ett.
Vadå "läser alla med en gång"? Den läser ett ackord åt gången, om än jävligt snabbt. Vill du att ett ackord ska spela klart innan nästa påbörjas får du väl lägga in en sleep i loopen eller i PlayAckord eller nåt.
Tack spango det var just vad jag gjorde, men jag tänkte att det var för "hemasnickrat".