Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
blutigeranfaenger
User
Beiträge: 65 Registriert: Dienstag 4. März 2014, 12:04
Samstag 25. Mai 2024, 16:02
Hallo zusammen,
ich möchte gerne aus unten stehendem Text folgendes Muster komplett entfernen:
\mark \markup { \box { BUCHSTABE } }
wobei Buchtabe für einen Großbuchstaben A-Z steht.
Ich habe es mit folgendem Skript probiert:
Code: Alles auswählen
#!/usr/bin/env python3
import re
text = """
\version "2.22.2"
violine = {
\clef "treble" | % 1
R1*8 | % 9
\mark \markup { \box { A } } R1*8 -\markup{ \tiny {Lija+Tambor} }
\mark \markup { \box { B } }
R1*8
\mark \markup { \box { C } }
r4 <f'' b''>2. \fermata :32
}
"""
# Regex-Muster zum Finden und Entfernen der gewünschten Elemente
pattern = r'\\mark\s+\\markup\s+\{\s*\\box\s*\{\s*[A-Z]\s*\}\s*\}'
# Entfernen der gefundenen Elemente
cleaned_text = re.sub(pattern, '', text)
# Ausgabe des bereinigten Textes
print(cleaned_text)
Leider funkioniert das aber nicht wie gewünscht! Es erscheint z.B.
\mark \markup {ox { A } }
und aus "\fermata" wird "ermata".
nezzcarth
User
Beiträge: 1762 Registriert: Samstag 16. April 2011, 12:47
Samstag 25. Mai 2024, 16:38
Das ist lilypond oder? Nimm einen geeigneten Parser. Mit normalen regulären Ausdrücken (alleine) wird das nur unstabiles Gefummel, u.a. da sie nicht für das korrekte Matchen von Klammerausdrücken geeignet sind (Ausnahme ist z.B. das externe Luapat, das aber eine sehr spezielle Variante von regex ist und ebenfalls ein externes Paket). Abgesehen davon muss in 'text' escaped oder ein raw string verwendet werden.
pillmuncher
User
Beiträge: 1530 Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel
Samstag 25. Mai 2024, 19:24
blutigeranfaenger hat geschrieben: Samstag 25. Mai 2024, 17:12
Ja, das ist Lilypond. Aber was meinst Du mit "Nimm einen geeigneten Parser"?
Parsen bedeutet, einen Text in grammatisch bedeutungsvolle Teile zu zerlegen. "Teile" auf Lateinisch heißt "partes", davon abgeleitet ist ein Programm, das das erledigt, ein Parser. Wenn man einen Text parsen will, braucht man die dazugehörende Grammatik. Hier ist die von Lilypond:
http://lilypond.web.fc2.com/v2.13.45/Do ... ammar.html
Leider scheint es für Lilypond nur fertige Parser in Scheme zu geben, für Python habe ich nach kurzem googlen nichts gefunden. Vielleicht hast du ja mehr Glück. Ansonsten, wenn du das in Python bauen willst, solltest du eine bestehende Parser-Bibliothek verwenden, am Besten eine, die es erlaubt, die syntaktischen Regeln ("die Grammatik") in der Form zu programmieren, wie in dem o.s. Link. Ich mag ja gerne Parserkombinatoren, wo man das direkt in Python schreiben kann, statt in einer extra Sprache wie yacc. Schau dir mal
PyParsing oder
Parsy an.
In specifications, Murphy's Law supersedes Ohm's.
__blackjack__
User
Beiträge: 14047 Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:
Sonntag 26. Mai 2024, 15:46
Habe mir `parce` mal angeschaut und wie man damit die entsprechenden Textstellen finden kann:
Code: Alles auswählen
#!/usr/bin/env python3
from functools import partial
import parce
from parce.lang.lilypond import LilyPond
SOURCE_TEXT = R"""
\version "2.22.2"
violine = {
\clef "treble" | % 1
R1*8 | % 9
\mark \markup { \box { A } } R1*8 -\markup{ \tiny {Lija+Tambor} }
\mark \markup { \box { B } }
R1*8
\mark \markup { \box { C } }
r4 <f'' b''>2. \fermata :32
}
"""
parse = partial(parce.root, LilyPond.root)
PATTERN_TOKENS = list(parse(R"\mark \markup { \box { SOME_TEXT } }").tokens())
def find_all(node, pattern_tokens):
first_pattern_token, *pattern_tokens = pattern_tokens
for start_token in node.query.all(
first_pattern_token.text, first_pattern_token.action
):
query = start_token.query
for pattern_token in pattern_tokens:
query = (
query.next.action(pattern_token.action)
if pattern_token.text == "SOME_TEXT"
else query.next(pattern_token.text, pattern_token.action)
)
end_token = query.pick()
if end_token is not None:
yield start_token.range(end_token)
def main():
tree = parse(SOURCE_TEXT)
tree.dump()
print(list(find_all(tree, PATTERN_TOKENS)))
if __name__ == "__main__":
main()
Ausgabe:
Code: Alles auswählen
<Context LilyPond.root at 1-266 (5 children)>
├╴<Token '\\version' at 1:9 (Keyword)>
├╴<Context LilyPond.list at 10-18 (1 child)>
│ ╰╴<Context LilyPond.string at 10-18 (3 children)>
│ ├╴<Token '"' at 10:11 (Literal.String)>
│ ├╴<Token '2.22.2' at 11:17 (Literal.String)>
│ ╰╴<Token '"' at 17:18 (Literal.String)>
├╴<Context LilyPond.list at 20-27 (1 child)>
│ ╰╴<Token 'violine' at 20:27 (Name.Variable.Definition)>
├╴<Token '=' at 28:29 (Delimiter.Operator.Assignment)>
╰╴<Context LilyPond.musiclist* at 31-266 (37 children)>
├╴<Token '{' at 31:32 (Delimiter.Bracket.Start)>
├╴<Token '\\clef' at 37:42 (Name.Builtin)>
├╴<Context LilyPond.list at 43-51 (1 child)>
│ ╰╴<Context LilyPond.string at 43-51 (3 children)>
│ ├╴<Token '"' at 43:44 (Literal.String)>
│ ├╴<Token 'treble' at 44:50 (Literal.String)>
│ ╰╴<Token '"' at 50:51 (Literal.String)>
├╴<Token '|' at 52:53 (Delimiter.Separator.PipeSymbol)>
├╴<Context LilyPond.singleline_comment at 54-57 (2 children)>
│ ├╴<Token '%' at 54:55 (Comment)>
│ ╰╴<Token ' 1' at 55:57 (Comment)>
├╴<Token 'R' at 62:63 (Text.Music.Rest)>
├╴<Token '1' at 63:64 (Literal.Number.Duration)>
├╴<Context LilyPond.duration at 64-66 (1 child)>
│ ╰╴<Context LilyPond.duration_scaling at 64-66 (2 children)>
│ ├╴<Token '*' at 64:65 (Literal.Number.Duration)>
│ ╰╴<Token '8' at 65:66 (Literal.Number.Duration.Scaling)>
├╴<Token '|' at 67:68 (Delimiter.Separator.PipeSymbol)>
├╴<Context LilyPond.singleline_comment at 69-72 (2 children)>
│ ├╴<Token '%' at 69:70 (Comment)>
│ ╰╴<Token ' 9' at 70:72 (Comment)>
├╴<Token '\\mark' at 77:82 (Name.Builtin)>
├╴<Context LilyPond.markup at 83-90 (1 child)>
│ ╰╴<Token '\\markup' at 83:90 (Keyword.Markup)>
├╴<Context LilyPond.markuplist at 91-107 (4 children)>
│ ├╴<Token '{' at 91:92 (Delimiter.Bracket.Markup.Start)>
│ ├╴<Token '\\box' at 93:97 (Name.Function.Markup)>
│ ├╴<Context LilyPond.markuplist at 98-105 (3 children)>
│ │ ├╴<Token '{' at 98:99 (Delimiter.Bracket.Markup.Start)>
│ │ ├╴<Token 'A' at 100:101 (Text)>
│ │ ╰╴<Token '}' at 104:105 (Delimiter.Bracket.Markup.End)>
│ ╰╴<Token '}' at 106:107 (Delimiter.Bracket.Markup.End)>
├╴<Token 'R' at 108:109 (Text.Music.Rest)>
├╴<Token '1' at 109:110 (Literal.Number.Duration)>
├╴<Context LilyPond.duration at 110-112 (1 child)>
│ ╰╴<Context LilyPond.duration_scaling at 110-112 (2 children)>
│ ├╴<Token '*' at 110:111 (Literal.Number.Duration)>
│ ╰╴<Token '8' at 111:112 (Literal.Number.Duration.Scaling)>
├╴<Token '-' at 113:114 (Delimiter.Direction)>
├╴<Context LilyPond.markup at 114-121 (1 child)>
│ ╰╴<Token '\\markup' at 114:121 (Keyword.Markup)>
├╴<Context LilyPond.markuplist at 121-144 (4 children)>
│ ├╴<Token '{' at 121:122 (Delimiter.Bracket.Markup.Start)>
│ ├╴<Token '\\tiny' at 123:128 (Name.Function.Markup)>
│ ├╴<Context LilyPond.markuplist at 129-142 (3 children)>
│ │ ├╴<Token '{' at 129:130 (Delimiter.Bracket.Markup.Start)>
│ │ ├╴<Token 'Lija+Tambor' at 130:141 (Text)>
│ │ ╰╴<Token '}' at 141:142 (Delimiter.Bracket.Markup.End)>
│ ╰╴<Token '}' at 143:144 (Delimiter.Bracket.Markup.End)>
├╴<Token '\\mark' at 149:154 (Name.Builtin)>
├╴<Context LilyPond.markup at 155-162 (1 child)>
│ ╰╴<Token '\\markup' at 155:162 (Keyword.Markup)>
├╴<Context LilyPond.markuplist at 163-179 (4 children)>
│ ├╴<Token '{' at 163:164 (Delimiter.Bracket.Markup.Start)>
│ ├╴<Token '\\box' at 165:169 (Name.Function.Markup)>
│ ├╴<Context LilyPond.markuplist at 170-177 (3 children)>
│ │ ├╴<Token '{' at 170:171 (Delimiter.Bracket.Markup.Start)>
│ │ ├╴<Token 'B' at 172:173 (Text)>
│ │ ╰╴<Token '}' at 176:177 (Delimiter.Bracket.Markup.End)>
│ ╰╴<Token '}' at 178:179 (Delimiter.Bracket.Markup.End)>
├╴<Token 'R' at 186:187 (Text.Music.Rest)>
├╴<Token '1' at 187:188 (Literal.Number.Duration)>
├╴<Context LilyPond.duration at 188-190 (1 child)>
│ ╰╴<Context LilyPond.duration_scaling at 188-190 (2 children)>
│ ├╴<Token '*' at 188:189 (Literal.Number.Duration)>
│ ╰╴<Token '8' at 189:190 (Literal.Number.Duration.Scaling)>
├╴<Token '\\mark' at 196:201 (Name.Builtin)>
├╴<Context LilyPond.markup at 202-209 (1 child)>
│ ╰╴<Token '\\markup' at 202:209 (Keyword.Markup)>
├╴<Context LilyPond.markuplist at 210-226 (4 children)>
│ ├╴<Token '{' at 210:211 (Delimiter.Bracket.Markup.Start)>
│ ├╴<Token '\\box' at 212:216 (Name.Function.Markup)>
│ ├╴<Context LilyPond.markuplist at 217-224 (3 children)>
│ │ ├╴<Token '{' at 217:218 (Delimiter.Bracket.Markup.Start)>
│ │ ├╴<Token 'C' at 219:220 (Text)>
│ │ ╰╴<Token '}' at 223:224 (Delimiter.Bracket.Markup.End)>
│ ╰╴<Token '}' at 225:226 (Delimiter.Bracket.Markup.End)>
├╴<Token 'r' at 232:233 (Text.Music.Rest)>
├╴<Token '4' at 233:234 (Literal.Number.Duration)>
├╴<Context LilyPond.chord at 235-244 (6 children)>
│ ├╴<Token '<' at 235:236 (Delimiter.Chord.Start)>
│ ├╴<Token 'f' at 236:237 (Text.Music.Pitch)>
│ ├╴<Context LilyPond.pitch at 237-239 (1 child)>
│ │ ╰╴<Token "''" at 237:239 (Text.Music.Pitch.Octave)>
│ ├╴<Token 'b' at 240:241 (Text.Music.Pitch)>
│ ├╴<Context LilyPond.pitch at 241-243 (1 child)>
│ │ ╰╴<Token "''" at 241:243 (Text.Music.Pitch.Octave)>
│ ╰╴<Token '>' at 243:244 (Delimiter.Chord.End)>
├╴<Token '2' at 244:245 (Literal.Number.Duration)>
├╴<Context LilyPond.duration at 245-246 (1 child)>
│ ╰╴<Token '.' at 245:246 (Literal.Number.Duration.Dot)>
├╴<Token '\\fermata' at 247:255 (Name.Script.Articulation)>
├╴<Token ':' at 256:257 (Delimiter.Tremolo)>
├╴<Token '32' at 257:259 (Literal.Number.Duration.Tremolo)>
╰╴<Token '}' at 265:266 (Delimiter.Bracket.End)>
[<Range LilyPond.musiclist* [77:107]>, <Range LilyPond.musiclist* [149:179]>, <Range LilyPond.musiclist* [196:226]>]
“Vir, intelligence has nothing to do with politics!” — Londo Mollari