Help with $substr script please?

Ah! Another glorious chance to display my lacking understanding of scripting and it’s terminology :wink:

I have a tag containing data like:

blablabla; blablabla2, whatever: interesting

Obviously I only want ‘interesting’ returned here.

Going through the documentation, this seemed a likely candidate:

$substr(text,start,end)

“Returns the substring beginning with the character at the start index, up to (but not including) the character at the end index. Indexes are zero-based. Negative numbers will be counted back from the end of the string. If the start or end indexes are left blank, they will default to the start and end of the string respectively.”

So I created:
$set(nicetag,$substr(%sourcetag%,:,))

But that will return the complete string, not only whats after the colon.
(p.s., I don’t require the space right after the colon either)

I thought to enter something for ‘end’ too, but failed with that too.
What am I doing wrong?

1 Like

There’s something implicitly documented here: the indexes are numbers (the first character in a string has index 0, the second one index 2, etc.). If you pass something as an index that can’t be converted to a number, Picard ignores that value.

Assuming that there’s only ever a single colon in the string, you want

$set(_indexofcolon,$add($find(%sourcetag%,:),1))
$set(artist,$strip($substr(%sourcetag%,%_indexofcolon%,)))

This first finds the index of the first colon, saves it as _indexofcolon, uses that as an index and (since you probably don’t want the whitespace after the colon to be part of the new value), strips the whitespace with $strip (if it exists).

/edit: Fixed the off-by-one error mentioned by others.

2 Likes

$substr is expecting integers for start and end, but you are providing the character ‘:’. To do what you want (return everything after the first occurrence of a colon), you would need something like:

$set(nicetag,$trim($substr(%sourcetag%,$find(%sourcetag%,:),),: ))

I know that looks pretty unwieldy, so you’re likely better off using a regular expression like:

$set(nicetag,$rsearch(%sourcetag%,:\\s*\([^:]+\)\$))
1 Like

Thanks guys!
I am going to try all proposed solutions, and stick to the one that seems to works best for me.
(and I hope to learn from it in the process…)

update;
I just asked my brain, and it says it likes the solution with the $trim function the most.
Working great.

I was in the process of writing my response, but you beat me to it. :wink:

One thing though… I think that your code will also return the colon at the start of the string, so you would have to add the colon to the $strip characters.

Also, I’ve added the bit about the inputs being integers to the draft Picard documentation that I’ve started working on. The project is on GitHub.

2 Likes

that 's correct
12345678910

Tested, and working great.
The perfect solution for my original question.

One of these days I’m gonna find me a new hobby.
They say golf is nice.

With the information that was handed to me in this thread, I thought to use it for another scenario.

This time I didn’t want everything after the “:” returned, but everything before it.
So I shoved things around a bit, and came up with this:

$set(0 TEST,$substr(%_cwp_work_1%,$find(%_cwp_work_1%,:)))

It works fine for tags that indeed contain a colon:

But if the source tags has no colon, it will return the source string, but it will also chop-off the last character:

So I probably need to add some ‘if-contains-colon’ statement here.
I should be able to figure that out with a clear mind, but for now I was wondering if this behaviour of $substr is correct, in that it removes the last character when ‘:’ is not matched?

I think you’re actually missing a comma in the script line you provided because it causes an error as shown.

The problem is that $find is returning “-1” when the search string (colon) is not found, and you are entering this as the end parameter to $substr which means “one character before the end of the string”. For what you want, try something like:

$set(_temp,$find(%_cwp_work_1%,:))$set(0_TEST,$substr(%_cwp_work_1%,,$if($lt(%_temp%,0),,%_temp%)))

That raises a good point. Perhaps $find should return “” if the string is not found, rather than “-1”. I wrote it to return “-1” because that’s the way the function works in Python.

1 Like

And your code misses an % (after %_temp )
( Let’s pick up golf together? :wink: )

No, I’m sorry, kidding of course. Thank you for continued support and speedy and informative replies!
I’m going to digest this all very soon. (not tonight though)

1 Like

Good catch. I’ll fix that in my earlier message. Thanks.

Just one more brief and impulsive brainfart for today:
Would the addition of a new function like $split perhaps be useful?
“split before a certain character/split after a certain character”

I’m accustomed to it from another piece of software, and I find it useful and not too hard to understand.

It’s certainly doable, but regular expressions work well for this sort of thing. For example, your “split before” would be:

$set(target,$rsearch(%source%,^\([^%split_character%]*\)))

and your “split after” would be:

$set(target,$rsearch(%source%,\([^%split_character%]*\$\)))

If you really want to see it added, I suggest putting in a ticket. Alternately, I could write a plugin for it easily enough.

1 Like

I’ve created PICARD-1781 to make the change, but before I do anything with it, I’d like some feedback and/or votes on the ticket. Thanks.

3 Likes

Nah, I’ll leave it up to you guys to estimate if you think something like that might be beneficial to more users.
I can also figure out using regex once in a while for some cases, but some days regex comes easy to me, and some days it makes me pulling my hairs out :wink:

1 Like

Me too, and I’ve been using them for years. :wink:

1 Like

I see it’s already going to be changed for 2.3.2. That’s great.