Help with Regex to remove suffix

I'm not sure if my regex is blatantly wrong or if its incorrect for the implementation of Regex in KB.
I just want to remove a suffix from a single line of text if it exists.
I want to remove ".new.01" from the end of a single line of text in the clipboard. The number could be anything from 01>99.

Sample lines:
Thing.new.01
Another thing
Yet another.new.02

My regex is:
(.*)(\.new\.\d{2})?
This captures the whole line in capture group 1. I expected it to capture the 'new.01' part in capture group 2 and the whole line in capture group 1 if the suffix didnt exist.

What am I doing wrong, I'm sure I've had very similar regex's working before.

Thanks.

This is very strange. When I use your Regex, this happens:

image

Local_Match1: "Thing.new.01"
Local_Match2: ""

But if I remove the trailing "?", I get the correct result:

image

Local_Match1: "Thing"
Local_Match2: ".new.01"

This makes no sense to me at all.

I know I'm not much help, but at least I can verify your results.

For the time being, you could do a workaround. Turn off the "Failure" options in the gear menu, use the regex without the "?", and check if %ActionResult% is "OK" or not. If it's "OK", then you've got your second value. If it's not "OK", then you know the suffix doesn't exist.

It works the other way round -- because the second part is optional, .* grabs everything regardless (I got caught out by this, very publicly, on this Forum a couple of weeks ago :wink: ).

If you want to chop the end off it it's there, it's better to use a "Search and Replace" replacing with nothing, and with the pattern anchored to the end of the string:

image

If you want to handle multiple lines on the Clipboard, chopping the end of each, then use mulitline option:

image

If, instead of chopping "in place", you want to separate into 1 or 2 parts depending on if the ending is there, use "Search Using Regular Expression" but anchor both start and end and make your .* non-greedy:

image

1 Like

Thank you @Nige_S !

Yes, in retrospect I have overengineered it - the search and replace is actually a simpler and more elegant solution.
I did play around with anchors because I suspected the .* was greedy, but I didn't try them at both ends.

Your last one works, though I assumed putting the first optional quantifier on the outside of the first capture group would yield the same result, alas it doesn't...but putting it inside the group works.

I'm at the pinnacle of my brains capability to comprehend complex regex's! @DanThomas

I'm at the pinnacle of my brains capability to comprehend complex regexs!

Putting it outside the capture group makes the group optional (as with the second group). Putting it inside, immediately after the *, makes the * "non-greedy" -- matching as few characters as possible.

1 Like

And, FWIW, splitting yields simpler patterns than search.

Without numeric suffix.kmmacros (2.3 KB)


Expand disclosure triangle to view JS source
return kmvar.local_Source
    .split("\n")
    .map(s => {
        const parts = s.split(".");

        return isNaN(parts[parts.length - 1])
            ? s
            : parts.slice(0, -1).join(".");
    })
    .join("\n");