Keyboard Maestro Regular Expression Bug? Trim Whitespace from Start and End of a String

@thoffman666 Your reply landed while I was typing mine. Did I capture what you had in mind, or are you thinking of yet another issue?

Steve

I agree with your reply, @SLWorona . More generically, I was just pointing out that @JMichaelTX 's complaint about KM's flavor of regex, while valid, is not really what we have been talking about in this thread.

BTW, I just completely coinicidently ran in to exactly the same issue with BBEdit.

Source:

hello
there

Regex search (.*) and replace with \1: β€œ\1”

Result:

hello: β€œhello”: β€œβ€
there: β€œthere”: β€œβ€

Using (.+) resolves the issue.

So this is a fairly generic issue revolving around matching empty strings.

Actually it fully relates to the issue Chris @ccstone is posting.
Chris tried to provide an alternate Regex pattern.

However, this Regex pattern always works WHEN you do NOT do a GLOBAL search/replace:

SEARCH FOR:
\R*$

Example Results from Regex101.com with GLOBAL flag turned OFF:

See Regex101.com Example

image

KM Test Macro that FAILS because it always does a GLOBAL search/replace:

Example Results From KM

image

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

MACRO:   Make sure text ends with LF

-~~~ VER: 1.0    2021-06-17 ~~~
Requires: KM 8.2.4+   macOS 10.11 (El Capitan)+
(Macro was written & tested using KM 9.0+ on macOS 10.14.5 (Mojave))

DOWNLOAD Macro File:

Make sure text ends with LF.kmmacros
Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.


Sorry, Peter, but this is incorrect.
BBEdit always does a GLOBAL search/replace, and has the "multi-line" mode ON.

So, if you turn OFF "multi-line", and only do a find next and replace, it works as expected:

Demo_BBEdit-Replace-AN

Sorry, what?

I just did exactly what I said, so it is not incorrect.

If you do a global search and replace, as I did, to transform words exactly as I wanted, I get the same bogus behaviour.

I don't care if it has other modes in other ways o operating, the fact is it behaves in exactly the same bogus way when doing a global search and replace on the document.

Adding (?-m) makes no difference in this case.

Clicking Find, and the Replace & Find over and over again works properly, but clicking Replace All shows exactly the same bogus handling of empty matches as seen in the original post.

You are totally missing the point. If you do NOT do a global/search/replace, it works fine everywhere.
So, the point is that the KM Search/Replace needs to have a "First Match" option.

I am not missing your point - I am ignoring your point as irrelevant to the discussion.

In the OPs case and in my case, the goal is a global search & replace.

It does not work if you don't do a global search & replace because it would only replace the first line (or in the OPs case, the start of the text).

You are arguing that a bogus behaviour that causes multiple replacements doesn't happen if you don't do multiple replacements, which is obvious but not helpful since the purpose in both cases is to do a global search & replace.

Even if I add a switch to the Search & Replace action to do only a single replacement, it would not have resolved the OPs problem, nor would it have resolved my problem, so this discussion is in no way an argument in favour of adding such a switch.

I don't think that is correct:

The issue is the replacement at the END of the string.
When you have GLOBAL turn on, it fails.
When GLOBAL is OFF, it works.

I know this because Chris @ccstone and I discussed and tested this privately.
It is unfortunately that the use case he presented at the top does not make that clear.

So, rather than belabout this any further, I will post a new topic with a new use case that clearly illustrates the issue.

BTW, Peter: You seem to be using the RegEx engine provided by AppKit ("TRE"). I used that in Find Any File initially, but ran into two issues:

  1. It tends to crash, especially on binary data.
  2. It does not support many advanced regex expr, such as "(?!^ABC$)".

I resolved this all by using PCRE2 instead. Had to build it and include as a lib, but since then I had not a single crash any more related to regex use.

2 Likes

Well, I think there is a role for a regular expression here, but perhaps we only need a simple one ?

[\r\n]+
Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    const
        txt = Application("Keyboard Maestro Engine")
        .getvariable("testDataStr");

    const main = () =>
        unlines(
            lines(txt).flatMap(x => {
                const trimmed = x.trim();

                return trimmed ? (
                    [trimmed]
                ) : [];
            })
        );


    // --------------------- GENERIC ---------------------

    // lines :: String -> [String]
    const lines = s =>
        // A list of strings derived from a single
        // string delimited by newline and or CR.
        0 < s.length ? (
            s.split(/[\r\n]+/u)
        ) : [];

    // unlines :: [String] -> String
    const unlines = xs =>
        // A single string formed by the intercalation
        // of a list of strings with the newline character.
        xs.join("\n");

    return main();
})();