Author Topic: regex (regular expressions) - open discussion topic  (Read 28858 times)

hiccup

  • Sr. Member
  • ****
  • Posts: 7789
This is a topic for the purpose of having open discussions on the topic of RegEx. (regular expressions)

This seems like a good idea considering this is a rather special subject that will probably prove to be a challenge for most MusicBee users, and having a topic like this might be useful, even if just for scrolling through it to get some ideas and suggestions on the matter.

And with any luck, members with a good knowledge and understanding of regex might subscribe to this topic to get notifications on new post, so to be able to jump in to help other members with their regex challenges.

___

update:

Some links that I find to be useful:

Regular Expressions: coding, examples, testing resources  (a great RegEx overview/tutorial/cheatsheet tailored towards MusicBee by forum member karbock)
https://getmusicbee.com/forum/index.php?topic=38817.0

Cheatsheets:
http://regexstorm.net/reference
http://www.rexegg.com/regex-quickstart.html/regex-csharp.html#chars

Microsoft's RegEx reference guide:
https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference

Online RegEx testers:
http://regexstorm.net/tester
https://regex101.com/
https://regexr.com/
https://www.regexplanet.com/advanced/dotnet/index.html

RegEx Tutorials:
http://www.rexegg.com/regex-quickstart.html/regex-csharp.html
https://www.regular-expressions.info/quickstart.html
https://www.codeproject.com/Articles/9099/The-30-Minute-Regex-Tutorial
https://regexone.com/

A MusicBee forum thread where you are invited to post your RegEx formulas that you believe may be useful to others:
https://getmusicbee.com/forum/index.php?topic=21150.0

A handy little RegEx test utility created by Steven:
download MusicBee RegEx test utility
Last Edit: July 08, 2023, 11:01:47 AM by hiccup

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
Subscribed.  I'll try to offer explanations with any regex formulas I post.  That's I how learned the syntax.

hiccup

  • Sr. Member
  • ****
  • Posts: 7789
That would be great. Even at many 'tutorials for beginners' they fail/omit to describe in plain spoken language what is happening in a formula or an expression.
Last Edit: February 06, 2017, 10:56:53 AM by hiccup

Alumni

  • Sr. Member
  • ****
  • Posts: 1007
I would appreciate help with this formula for now playing:

if %contentgroup% has value "classical" then display %composer%:_ otherwise display nothing

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
I would appreciate help with this formula for now playing:

if %contentgroup% has value "classical" then display %composer%:_ otherwise display nothing
The virtualtag you want doesn't need regex.  I'm just going by what you wrote above.

Code
$if($contains(<grouping>,classical),<composer>":_",)

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
That would be great. Even at many 'tutorials for beginners' they fail/omit to describe in plain spoken language what is happening in a formula or an expression.
Just going off from the virtualtags I showed you in the other thread

First thing first, everyone should try http://regexr.com/, their cheatsheet was extremely helpful for me learning the regex syntax (I have no affiliation with the site).

General $rxreplace virtualtag formula: $RxReplace(<field>,"regex-pattern","replace-text")

Purpose: Title (Live) -> (Live)
Virtualtag: $RxReplace(<Title>,"(^.*)(\([Ll]ive\))","$2")

Explanation (read the regex left to right):

( ) = Capturing parentheses (or capture group).  Content enclosed by them are captured into memory and can be recalled.  In the above regex pattern, there are two captured groups.  The content from the first capturing parentheses can be returned using "$1" and contents from the second can be returned using "$2".  If there was a third, one would use $3, a fourth $4, so on and so forth.

^ = Beginning of a line
$ = End of the line

.* = . (any character), * (matches none or more of the proceeding token, here ".").  .* = any number of characters going rightward.  For example, ".*" by itself matches an entire line since it selects "." any character and "*" any number of characters.  Other examples, K.* = selects K and every character following K to the end of the line; .*K = selects everything from the beginning of the line to the last K.  .*? = The "?" means that the searching will be non-greedy, so .*?K = selects everything from the start of the line to the first K encountered.

^[Ll]ive$ = The brackets here mean that any of the characters included within it will match the single character.  Here, [Ll]ive means that the regex-pattern will find the words "Live" or "live".  Likewise, [FfLl]ive will find the words Five, five, Live and live.  On the flip side, adding a "^" at the beginning of the bracket array, such as [^Ll]ive, will result finding any four letter word having the last three letters "ive" while excluding "Live" and "live" from the results.

Note, if the two anchors ^ and $ were not there, then [Ll]ive will also select Live or live in the following words: Livermore, alive, olive, lively (you get the picture).  In the regex-pattern at the top, [Ll]ive is bordered by parentheses, so we use that to demarcate it from other words we don't want to match up with our pattern.  As for why the parenthesis are preceded by \, read the next paragraph.

Punctuation marks = What if someone wants to find parenthesis or periods? Use escape characters.  It means that having a "\" precede a character that is used in regex-patterns (like . ( ) [ ]), will mean that regex-pattern will search for those characters.  From above, \( means that regex-pattern will search for a parenthesis rather than establishing another capturing group.  Likewise \. means that a period will be searched rather than any character.

"$2" = This is the replace-text portion of $RxReplace.  Here, I'm telling it to replace <title> with whatever content is in the second captured group.
Last Edit: February 12, 2017, 10:15:29 PM by theta_wave

marlonob

  • Jr. Member
  • **
  • Posts: 43
Hi, everyone:


Does anyone know whether is possible to use the content of a <tag> (as a literal string) in the expression?

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
Hi, everyone:


Does anyone know whether is possible to use the content of a <tag> (as a literal string) in the expression?
I would think so since regex is all about manipulating the text contents in <tag>.  Do you have an example of what you wanted to do?

marlonob

  • Jr. Member
  • **
  • Posts: 43
Do you have an example of what you wanted to do?

Yes. I have a virtual tag (for classical) that deletes the work part of the title an leaves only the particular information of the track, like this:


Where (for the first track):
Work:   Symphony no. 4 in D minor, op. 120
Title:  Symphony no. 4 in D minor, op. 120: I. Ziemlich langsam - Lebhaft
Title-: ⋮I. Ziemlich langsam - Lebhaft


<Title-> is my virtual tag, defined as
$RxReplace($Replace(<Title>,<Work>,⋮),"⋮[ :,]*","⋮")


The problem occurs when the <Work> is used in the part of the title that I want to preserve. Example:

See track 06, where:
Work:   La noche de los mayas
Title:  La noche de los mayas: I. La noche de los mayas
Title-: ⋮I. ⋮

The expected <Title-> is
⋮I. La noche de los mayas

So, I’d rather use something like
$RxReplace(<Title>,"^"<Work>"[ :,]*(.+)","⋮$1")

 for my virtual tag, but I can’t find a way to do so.

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
Where (for the first track):
Work:   Symphony no. 4 in D minor, op. 120
Title:  Symphony no. 4 in D minor, op. 120: I. Ziemlich langsam - Lebhaft
Title-: ⋮I. Ziemlich langsam - Lebhaft

<Title-> is my virtual tag, defined as
$RxReplace($Replace(<Title>,<Work>,⋮),"⋮[ :,]*","⋮")

See track 06, where:
Work:   La noche de los mayas
Title:  La noche de los mayas: I. La noche de los mayas
Title-: ⋮I. ⋮

 The expected <Title-> is
⋮I. La noche de los mayas

So, I’d rather use something like
$RxReplace(<Title>,"^"<Work>"[ :,]*(.+)","⋮$1")

 for my virtual tag, but I can’t find a way to do so.

Hmm, I don't know why you need to include <work> in your regex when you can still easily parse <Title> without including that tag field.  I don't know the significance of "⋮" in your setup, but I'll include it anyways.  You seem to know your way around regex, so you can remove it if you don't need it.

What I would use for <Title->:
Code
$rxreplace(<Title>,"(^.+?)(\:\s)(.*$)","⋮$3")
The "?" just makes the search non-greedy, so it will stop when it encounters the first ": ".  "\s" simply denotes whitespace.  I didn't need to escape the ":", but I guess that's just old practice from the days I was learning regex and felt it was better to escape a weird character rather than finding out after completing the regex the inoperative expression was due to not escaping said character.

For the following <Title>:
Symphony no. 4 in D minor, op. 120: I. Ziemlich langsam - Lebhaft
to
⋮I. Ziemlich langsam - Lebhaft

La noche de los mayas: I. La noche de los mayas
to
⋮I. La noche de los mayas

Die Entführung aus dem Serail (The Abduction from the Seraglio), K.384: Act III, No.21b. Chorus: "Bassa Selim leve lange!"
to
⋮Act III, No.21b. Chorus: "Bassa Selim leve lange!"


Edit, mini-editoral: The addition of the <Work> field is nice, but I'm lazy and I don't want to retag 20k files with <Work> or even create a advance search and replace setting.  Since all of my classical music follows the "Work: Movement" format, I simply use regex in a virtualtag for the job: $rxreplace(<Title>,"(^.+?)(\:\s)(.*$)","$1")
Last Edit: February 19, 2017, 06:29:36 PM by theta_wave

hiccup

  • Sr. Member
  • ****
  • Posts: 7789

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
$rxreplace(<Title>,"(^.+?)(\:\s)(.*$)","⋮$2")

I think the $2 at the end should be $3 ?
Noted and edited prior to your post :).  Heh, I guess I was typing a little fast and didn't bother checking.

hiccup

  • Sr. Member
  • ****
  • Posts: 7789
Noted and edited prior to your post :).  Heh, I guess I was typing a little fast and didn't bother checking.

Just wanted to say your contributions and explanations in this thread are really great.
Without it I would probably still be very lost and confused.
And look at me now, already correcting a black-belt.
hahaha

theta_wave

  • Sr. Member
  • ****
  • Posts: 680
Just wanted to say your contributions and explanations in this thread are really great.
Without it I would probably still be very lost and confused.
And look at me now, already correcting a black-belt.
hahaha
Thanks for the kind words.  I learned regex mostly by googling the problem I wanted to be solved and reading the explanations from users at stackoverflow.  Thus, I am nowhere near a black belt.  Maybe brown belt  ;)

hiccup

  • Sr. Member
  • ****
  • Posts: 7789
Since all of my classical music follows the "Work: Movement" format, I simply use regex in a virtualtag for the job: $rxreplace(<Title>,"(^.+?)(\:\s)(.*$)","$1")

I am guessing you mean $3 at the end here too?