Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Search notes and Replace with <notes> (chordsymbol) menu command or maybe snippet

14 views
Skip to first unread message

Eef Weenink

unread,
Jan 11, 2024, 3:48:28 PM1/11/24
to Frescobaldi
For figures bass exercises I have to replace notes with chords. 
First step I do is: 
place <> around every note

I want like to do that with search and command or maybe a snippet (if that would be easy to do). An example: 
--------------------
    bes2 fis2.        
        g2. a'4  r2 
        bes4 a4 g4 fis4      
         bes,2*2  R1
------------------------
After command is done, it should look like this: 
--------------
    <bes>2 <fis>2.        
        <g>2. <a'>4  r2 
        <bes>4 <a>4 <g>4 <fis>4      
         <bes,>2*2  R1 <c>1
----------------------
Now I do this in x steps, searching for notename and replace <notename> 
that is a lot work with many errors, like replace  b with <b> before I did the bes, what gives <b>es . And that ends in an error, 

regards, Eef 

Kevin Cole

unread,
Jan 11, 2024, 5:05:44 PM1/11/24
to fresc...@googlegroups.com
"This sounds like a job for... Superman! Er, I mean regex!" ;-) a.k.a.
regular expressions.

Someone who is more clever with regular expressions can probably come
up with a less ugly / complex regex, but here's my stab at it, which
mostly works.

1. Check the "regex" box to the right of the search
2. Use the search term:
"([ \t\n])+?([a-g])([ei]s)?([\',])*(16)?([1248])?([\.])?"
3. Use the replace term:
"\1<\2\3\4>\5\6\7"

Type carefully. ;-) And remove the quote marks. They're only for your benefit.

It's not perfect: For example, "\clef bass" becomes "\clef <b>ass" and
god help you if you have lyrics or lots of other verbage in there...
But it's a good start.

See also:
https://frescobaldi.org/uguide#help_search_replace
https://docs.python.org/3/library/re.html#regular-expression-syntax

Eef Weenink

unread,
Jan 12, 2024, 1:56:30 AM1/12/24
to Frescobaldi
Dear Kevin, Thank you for your fast (and at first looks complex) answer.
Let me see if I understand this a bit. 
  • In search:  ([ \t])+?([a-g])([ei]s)?([\',])*
  • In search string what is found and between () is saved as var1 var2 var3 etc.
  • In replace \1 \2 \3 are used to place var1 var2 var3 etc. 
  • there are 4 groups ()
    • ([ \t])+?    %finds all spaces, tabs (I left the \n out to keep my layout)
                        % I did not understand the +? (yet)
    • ([a-g])       % finds all notenames
    • ([ei]s)       % finds es and is 
                        % I did not understand the ? (yet)
    • ([\',])         % finds the octave ups and downs 
                        % I did not understand the * (yet)
  • In replace:  \1<\2\3\4>
    • First group is replaced with spaces and tabs + "<"
    • second and third group are replaced as they are
    • last group is replace with var4 + ">" 
OK, have to read a bit to understand what the + ? and * do. 

Regards, Eef 
Op donderdag 11 januari 2024 om 23:05:44 UTC+1 schreef dc....@gmail.com:

Kevin Cole

unread,
Jan 12, 2024, 8:24:36 AM1/12/24
to fresc...@googlegroups.com
On Fri, Jan 12, 2024 at 1:56 AM Eef Weenink <h.e.w...@de-erve.nl> wrote:

> Dear Kevin, Thank you for your fast (and at first looks complex) answer.
> Let me see if I understand this a bit.
>
> In search: ([ \t])+?([a-g])([ei]s)?([\',])*
> In search string what is found and between () is saved as var1 var2 var3 etc.
> In replace \1 \2 \3 are used to place var1 var2 var3 etc.
> there are 4 groups ()
>
> ([ \t])+? %finds all spaces, tabs (I left the \n out to keep my layout)
> % I did not understand the +? (yet)
> ([a-g]) % finds all notenames
> ([ei]s) % finds es and is
> % I did not understand the ? (yet)
> ([\',]) % finds the octave ups and downs
> % I did not understand the * (yet)
>
> In replace: \1<\2\3\4>
>
> First group is replaced with spaces and tabs + "<"
> second and third group are replaced as they are
> last group is replace with var4 + ">"
>
> OK, have to read a bit to understand what the + ? and * do.

I may have gotten a bit sloppy trying to answer relatively quickly.
And as I said, some regex wizard can probably come up with a better
beastie. Some of the problems can be fixed using the "OR" modifier:
the vertical bar. But a lot of the first draft is predicated on the
belief that you're not going to feed insanely complicated weird or
broken code to the regex. And that you'll make a backup before
unleashing the monster to devour your code. ;-)

* means "zero or more" of the preceding

? can be used to indicate zero or one but no more... However, when
combined with + or * it is a "non-greedy" match modifier.

+ means "at least one" ("one or more")

So...

"([,\'])*" means that you can go up or down more than one octave... or
not at all. c c' c''''' c, c,,,,, are all captured by that.

"([ei]s)?" means you can only have zero or one occurrence of "es" or
"is". I guess you could run into trouble here: The stuff I score never
gets into double-flats or double-sharps. So when I wrote it, I wasn't
thinking about that. That could be fixed by replacing the "?" with
"{0,2}" which sets a range: zero, one or two "es" or "is". I don't
know enough about music to know if triple-flats, or quadruple-sharps
are a thing. But if they are, then the person using them should seek
the help of a mental health professional. ;-)

"(16)?([1248])?([\.])?" means that the note does not need to be
followed by a duration, but if it is, it can only be followed by a
single duration. This one's not perfect. For example, c can be
followed by nothing, or by 16, or by 1, 2, 4 or 8, but not 12, or 24,
followed by "." It falls apart if you've got bad data to start with:
"c161", "c162", "c164", "c168", and "c." are all valid matches: The
first four meet the condition "zero or one occurrence of "16" AND
"zero or one occurrence" of "1", "2". "4" or "8", and the last example
is the same: no 16, no 1, 2, 4, or 8, but one "." This is one that
could be improved by changing it to "(1|2|4|8|16|32)?([\.])?" I don't
know why I didn't write it that way. And now it allows for a 32nd
note. It takes care of the number problem but still allows for "c."

"([ \t\n])+?" just isn't right. I want to indicate at the beginning
and ending of each note, there should be a whitespace delimiter,
either a newline, a tab or a space. But I cannot use "^" or "$"
because then, the "e8" in a line like "c1 f4. e8 g2" wouldn't match. I
tried a few different variations, and none of them satisfied me
completely. When I sent the message, I forgot to remove the "?" from
that one... I think. I want at least one delimiter before the letter
name. Different variations of this ended up skipping different valid
matches. I just gave up and said "it's close enough".

There are other problems as well: If your string of notes includes
lots of stuff like
c2\fermata | f2 | g2^"CHORUS"
the regex is going to make a mess of it.

Some of that can be fixed with the NOT modifier ^ For example
"([^a-z0-9])+" would mean at least one non-alphanumeric character. And
then there are the other backslash combinations which cover groups of
characters and idioms like "word" or "non-word". Those would probably
fix A LOT of the problems. I just always have to look them up and was
feeling lazy, but if you dig deep into the last link I provided, that
covers all the arcane, occult ins and outs of the Python regex
processor, you can probably construct the perfect regex before you
die, but I'm guessing you'd rather write music. ;-)

Eef Weenink

unread,
Jan 12, 2024, 8:54:39 AM1/12/24
to Frescobaldi
"you can probably construct the perfect regex before you
die, but I'm guessing you'd rather write music. ;-)"

Right, I rather make music, then die :-) 

Op vrijdag 12 januari 2024 om 14:24:36 UTC+1 schreef dc....@gmail.com:

Knute Snortum

unread,
Jan 12, 2024, 9:43:32 AM1/12/24
to fresc...@googlegroups.com
On Fri, Jan 12, 2024 at 5:24 AM Kevin Cole <dc....@gmail.com> wrote:

"([ \t\n])+?" just isn't right. I want to indicate at the beginning
and ending of each note, there should be a whitespace delimiter,
either a newline, a tab or a space. But I cannot use "^" or "$"
because then, the "e8" in a line like "c1 f4. e8 g2" wouldn't match. I
tried a few different variations, and none of them satisfied me
completely. When I sent the message, I forgot to remove the "?" from
that one... I think. I want at least one delimiter before the letter
name. Different variations of this ended up skipping different valid
matches. I just gave up and said "it's close enough".

You should be able to use \s for whitespace.


There are other problems as well: If your string of notes includes
lots of stuff like
c2\fermata | f2 | g2^"CHORUS"
the regex is going to make a mess of it.

Some of that can be fixed with the NOT modifier ^ For example
"([^a-z0-9])+" would mean at least one non-alphanumeric character. And
then there are the other backslash combinations which cover groups of
characters and idioms like "word" or "non-word". Those would probably
fix A LOT of the problems. I just always have to look them up and was
feeling lazy, but if you dig deep into the last link I provided, that
covers all the arcane, occult ins and outs of the Python regex
processor, you can probably construct the perfect regex before you
die, but I'm guessing you'd rather write music. ;-)

You can almost use \w for this.  It translates to [a-zA-Z0-9_].  Ago, \b matches a word boundary and is zero-width. 

HTH 

--
Knute Snortum
 

Kevin Cole

unread,
Jan 12, 2024, 10:38:48 AM1/12/24
to fresc...@googlegroups.com
On Fri, Jan 12, 2024 at 9:43 AM Knute Snortum <ksno...@gmail.com> wrote:

> You should be able to use \s for whitespace.
...
> You can almost use \w for this. It translates to [a-zA-Z0-9_]. Ago, \b matches a word boundary and is zero-width.

Thanks. As I went back and started looking at some of the \this and
\that, I started seeing lots of ways to improve it, but I never
remember all the backslash options. And I mess up the greedy /
non-greedy stuff too. Every time I need them I have to go back and
re-read the Python page or the grep man page. Yesterday, I was too
lazy to bother, and just tried to whip up something quick and included
a link to documentation on how to improve it.

(I do use the (...|...|...) "this or that or the other" construct a
lot and, occasionally the {minimum, maximum} construct. I guess I was
half-asleep yesterday, since today it was obvious that I should have
used them in my example yesterday.)

Eef Weenink

unread,
Jan 12, 2024, 10:51:48 AM1/12/24
to fresc...@googlegroups.com

Well you guys, now you are going too fast for me. Too many \this and |that at one time.
And how to ever remember this all.
This thought brings me to the following:
“Can you help me to transform this into a snippet for the Frescobaldi menu?”
Then I can use it fast when needed. And because all is in the script of the snippet is much easier then remembering, and easier to do some quick modifications (and or) make a copy for another regular search/replace task?
BTW: Is there anywhere on the internet an archive with snippets people have made, for the use and benefit of us all?

Regards, Eef

 

--
Frescobaldi homepage: http://www.frescobaldi.org/
Mailing list: http://groups.google.com/group/frescobaldi
Issue tracker: https://github.com/frescobaldi/frescobaldi/issues
---
You received this message because you are subscribed to the Google Groups "Frescobaldi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to frescobaldi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/frescobaldi/CA%2BpvXReZA1txtXyVXsqPkK449JJaArXif%3DZ-yhT33%3Dmu5YG80Q%40mail.gmail.com.

Knute Snortum

unread,
Jan 12, 2024, 11:25:37 AM1/12/24
to fresc...@googlegroups.com
On Fri, Jan 12, 2024 at 7:51 AM Eef Weenink <eefwe...@outlook.com> wrote:

Well you guys, now you are going too fast for me. Too many \this and |that at one time.
And how to ever remember this all.


Regular expressions are a very difficult concept that takes some getting used to.
 

This thought brings me to the following:
“Can you help me to transform this into a snippet for the Frescobaldi menu?”


I'm not sure a snippet is going to be helpful, since this is a search and replace, but maybe someone knows how to do that. 

Then I can use it fast when needed. And because all is in the script of the snippet is much easier then remembering, and easier to do some quick modifications (and or) make a copy for another regular search/replace task?
BTW: Is there anywhere on the internet an archive with snippets people have made, for the use and benefit of us all?


Well, there's this for LilyPond:



--
Knute Snortum

Eef Weenink

unread,
Jan 12, 2024, 11:38:35 AM1/12/24
to fresc...@googlegroups.com

Well, there's this for LilyPond:

 

 

And for Frescobaldi? Maybe also?

Eef Weenink

unread,
Jan 12, 2024, 4:57:16 PM1/12/24
to fresc...@googlegroups.com

This thought brings me to the following:
“Can you help me to transform this into a snippet for the Frescobaldi menu?

I'm not sure a snippet is going to be helpful, since this is a search and replace, but maybe someone knows how to do that. 

---------------------------
Well, as an example: I use an app on my iPhone, what is very well in reading music. It exports the results however as a messy Musicxml. After import in Frescobaldi I have to do a lot of search and replacement to get nice looking strings to be used in my arrangements etc. A snippet with all actions I have to do, would make this more then a bit easier.

And yes it is possible. I did some searching, and with trial and error, this is a simple example to find and remove barchecks at end of the line:

-*- python;

import re

text =(re.sub('\| % \w*|\\barNumberCheck \#\w*','',text))

-------------------------
*  the regex module is imported
* re.sub has three inputparts:

  • What to search for
  • What to replace
  • Variable to search and replace in (in Frescobaldi always ‘text”.

 

Regards, Eef


 

Then I can use it fast when needed. And because all is in the script of the snippet is much easier then remembering, and easier to do some quick modifications (and or) make a copy for another regular search/replace task?
BTW: Is there anywhere on the internet an archive with snippets people have made, for the use and benefit of us all?

 

Well, there's this for LilyPond:

 

 

--

Knute Snortum

 

--

Frescobaldi homepage: http://www.frescobaldi.org/
Mailing list: http://groups.google.com/group/frescobaldi
Issue tracker: https://github.com/frescobaldi/frescobaldi/issues
---
You received this message because you are subscribed to the Google Groups "Frescobaldi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to frescobaldi...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages