Help with conditional and regex

Hi Taggers,
after I decided how to manage cover songs, I need a little help writing an Action.
I am a *nix user so I know some RegEx, but I need help with MP3tag syntax.

  1. If %title% equals to ".*(.* cover)$" then OriginalArtist=$2
    ($2 should be the second .* on the regex expression, right?)
  2. If OriginalArtist is not empty and %title% is not ".*cover)$", then %title% = %title% + " (%OriginalArtist% Cover)"

I'm trying to reach a "one touch" workflow:

  1. Use auto-numbering to add TrackNumber (number/total) and DiscNumber (number/total)
  2. "Standardize" (to my needs) various info normally put on title (like "featuring","cover","live","acoustic", etc.)
  3. Adjust Capitalization (I Love The All Caps Format but I had to fight with roman numbers)
  4. TAG -> Filename (Right now I have two formats to choose if album is one or multi-disc, I will need a little help extracting total discs number and choose the right format automatically)

Maybe I was crazy already...maybe this quarantine gives me too much time to spend on computer :smiley:


Please enclose those code snippets in accent grave (top-left to bottom right) - otherwise it is almost impossible to find the problems if parts of the expression are missing.

That is not "real" code, that's why I need help :wink:

Ahm no.
You have to enclose the parts that you want to address with $x in parenthesis.
If you want to find out if a string is part of another string, use $strstr(), e.g. $strstr(%title%,"cover")
So one could do something like an of the type Action "Format value" for ORIGARTIST
Format string: $ifgreater($strstr(%title%,cover),0,$regexp(%title%,.* (.*) cover,$1),)

Could be an action of the type "Format value" for TITLE
Format string: $ifgreater($strstr(%title%,cover),0,%title%[ %origartist% cover],%title%)

The numbering wizard cannot be called in an action.

You need a separate action following the case adjustment that deals with all the exceptions like the Roman numerals and probably all the "McCoys" and others.

Is an action of the type "Format value" for _FILENAME where you enter the field variables as format string.
Please note that you can use the square brackets to hide string parts that may not be filled, e.g. [ CD $num(%discnumber%,1)\]

1 Like

Wow ohrenkino,
you gave me so many info, thank you!
I wrote I'm trying to reach a "workflow" and not a "single click magic wand" action.
"Capitalization" action reached 18 rows, I will go with this "Original Artist" action.

Thank you

Ok, now I have ORIGARTIST:

$ifgreater($strstr(%title%,' Cover)'),0,$regexp(%title%,'.* \((.*) [Cc]over\)$',$1),)

but I don't know if I'll use this action before case conversion so I need strstr to ignore case or use another function, is it possible?!

you could transform everything into lower case for the initial comparison.
$ifgreater($strstr($lower(%title%),' cover)'),0,$regexp(%title%,'.* \((.*) [Cc]over\)$',$1),)

1 Like

With latest regexp information I gave a look at my "Case" group-action and found that I have two actions, one to trim all leading spaces from _TAG and one for trailing spaces.
Now I found that there is a $trim function but I can't find the right action to trim all _TAG. I thought to use "Format value" but can't specify _TAG.

Any hint?

Yes, you have to specify each field. I think that _TAG is the whole tag data with probably only one leading and one trailing space - if at all.
You can perform functions that deal with data in a string, though, but not with field boundaries.

Wait, maybe I didn't understand, are you saying that _TAG is just one, big string with all tags data and it doesn't mean "every single tag"?! :open_mouth:

In my understanding the tag is the whole piece of metadata which is attached to a file. E.g. the V1 tag can be found at the end of a file, the V2 tag can be found (mostly) at the beginning.
The tag itself is then structured into fields.
You will find a similar naming convention in the help in the overview of supported tag fields.

I think you may be wrong as MP3tag supports _ALL, _TAG and _FILENAME and, from Actions and batch-operations tutorial, it looks like _TAG stands "for every single tag" expect filename, otherwise the example that Dano wrote is useless.
Don't you think?

The examples perform actions of the type "Replace with regular expression" which is an action that can be used for more or less any string or all characters. The same applies to actions of the type "Case conversion".

But these are actions. The question arose from

where the problem is that this scripting function produces a string without leading or trailing spaces - and the syntax requires that you either enter a string constant (which would be pointless as while entering, you could leave out the superfluous blanks) or a variable that can produce a (single) string where spaces at the beginning or end can be trimmed.
I was trying to argue that _TAG would still produce just one long single string with just one beginning and one end but no separation into fields.
But I may be wrong.
To apply scripting functions use actions of the type "Format value".

I think you agree with me that if _TAG is just one big string that examples (that remove leading and trailing spaces) are at least misleading. I would like to know how many users thought that _TAG stands for "every single tag", so I just did a test :
Edited title, artist and album tags adding spaces at the beginning and at the end and run the following action group


Extra spaces (leading and trailing) are removed from every tag. I think this prove that _TAG means "every tag".

Said that, do I need two separate actions or can I use the | (pipe) character?

I wrote the following to add "(original artist cover)" to title just if title doesn't contains " cover)" and length of origartist is>0:

$if($and($strstr($lower(%title%),' cover)')=0,$len(%origartist%)>0),%title% (%origartist% Cover),%title%)

But something doesn't work as expected.

Found it:
$if($and($eql($strstr($lower(%title%),' cover)'),0),$grtr($len(%origartist%),0)),%title% (%origartist% Cover),%title%)

Still no. You asked about the scripting function $trim() which requires a single string.
The example is replacing with a regular expression inside a complete string and simply tests "do I find spaces in front of a an end-of-field marker (a binary 0) and if so remove the spaces?" A pattern can be found multple times inside the single _TAG string and then be treated.
The example did not use the much more comfortable function $trim() which cuts both, the leading and trailing spaces, for _TAG.

This has hardly anything to do with the MP3tag scripting functions.
Please check out the help

Have a closer look at $eql() and $grtr().
You can check your expressions in the function Convert>Tag-Tag

Now I see your point and I thank you for your patience.

MP3tag uses something like awk does, where you can change RS (record separator, normally a newline) so it should be able to trim leading and trailing spaces from every "record" of one, big string.
So functions like $trim() rely on "standard/real" strings and some other can handle "big string with different record separator". :slight_smile:

Just to recap initial problem:

  1. Now I can extract original artist if title is "Title (OrigArtist Cover)":
    $ifgreater($strstr($lower(%title%),' cover)'),0,$regexp(%title%,'.* \((.*) [Cc]over\)$',$1),)
  2. If title doesn't show it is a cover and there is an OrigArtist tag, set title accordingly:
    $if($and($eql($strstr($lower(%title%),' cover)'),0),$grtr($len(%origartist%),0)),%title% (%origartist% Cover),%title%)

Now I'll work on disc numbers and do the _filename thing.


  1. Rename file with "%track% %title%" if single disc, otherwise use "%disc%-%track% %title":
    $ifgreater($regexp(%discnumber%,'.*/(.*)',$1),1,$num(%discnumber%,1)-$num(%track%,2) %title%,$num(%track%,2) %title%)

Not a "magic wand" but we are almost there :smiley:


You could shorten the whole thing to:
[$num(%discnumber%,1)-]%track% %title%
The square brackets enclose optional parts that only get used if the included field has a value.

Good to know it, but %discnumber% will always have a value (1/1).
I want to use it just if track is from a multi-disc album.