Cannot Get "Make Second Word With Uppercase First" to Work

Based on this macro I created this macro. However, the output is wrong. I want the output:

F001 This is a warning message!

How can I fix this (I've tried lots of versions now ...). Thank you in advance!

Make second word with uppercase first.kmmacros (4.0 KB)

Macro Image

Hey Hans,

You were using a greedy regular expression.

Always prototype your RegEx in a programming editor or a RegEx tester – and understand any differences their flavor of RegEx has with KM's ICU RegEx.

I'm recommending CotEditor for people who don't want to use BBEdit, because CotEditor uses ICU RegEx – is very mature now – and is free.

-Chris


Download Macro(s): Make second word with uppercase first.ccs.v1.kmmacros (4.2 KB)

Macro-Image

Keyboard Maestro Export

Macro-Notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
    • The user must ensure the macro is enabled.
    • The user must also ensure the macro's parent macro-group is enabled.
System Information
  • macOS 10.14.6
  • Keyboard Maestro v10.2

1 Like

Thanks again, Chris!

BTW: It's never good to be greedy ;).

Except when it is... :sunglasses:

And, of course, we can also do it with split and join

( easing some of the load on over-stretched regular expressions :slight_smile: )

e.g. in an Execute JavaScript for Automation action:

Application("Keyboard Maestro Engine")
.getvariable("sourceStr")
.split(/\s/gu)
.reduce(
    (a, x, i) => [
        ...a,
        i !== 1
            ? x
            : `${x[0].toLocaleUpperCase()}${x.slice(1)}`
    ],
    []
)
.join(" ");

Initial cap for second word.kmmacros (3.0 KB)

2 Likes

Hey Chris,

If you don't mind, I'd like to ask some further questions about the regular expression you use:

I see that \H and \h match a non-Horizontal White Space character and a Horizontal White Space character respectively.

My first question is: Why do you use these, instead of "\s"?

My second question: Can you please explain how ^(\H+\h+) can grep anything from the segment start up to the first space? I mean: Why don't you have to define any "printed" characters here?

Cheers,
Hans

Not answering for Chris, but attempting an explanation for my own benefit because I didn't grok this at first. Anything @ccstone says supersedes this!

To clarify, \H matches "anything that is not a horizontal whitespace character" -- subtly different to what you've written.

\s matches any whitespace -- spaces, tabs, but also linefeeds, carriage returns, form feeds... \h matches only horizontal whitespace, so not linefeeds etc. \S and \H invert those same rules. Chris is being beautifully precise, and stopping the regex from spilling over to any next line of text.

So the regex reads "From the start of the string, match one or more characters that aren't horizontal whitespace, then one or more that are horizontal whitespace, and put the whole lot into the first capture group. Match everything else after that, up to an end-of-line marker, and put that into the second capture group".

If you want to see the difference between \H and \S in action:

H vs S in regex.kmmacros (5.1 KB)

Image

I've put "Line" in the line to make it obvious -- if that was an empty line I'd be tearing my hair out trying to spot the problem!

As \H is "all the characters that aren't horizontal whitespace", that includes A, b, 3, :, etc, etc -- all the "printed" characters and more (including linefeeds, carriage returns...).

More info about \h vs \s here. And big thanks to @ccstone for yet another nugget.

1 Like

Thank you very much for the clarification! And yes, where would we be without Grandmasta Chris.

@Nige_S' description is more than adequate I think, but do ask if you have any more questions.

It might also be worth your time to peruse the formula on regex101.com and examine the breakdown it gives of the regular expression.

Keep in mind that RE101 does not provide access to the ICU flavor of regex – although PCRE is reasonably close there are definite differences.

Never take for grated that a regex working in regex101.com will work in Keyboard Maestro – always test in an editor that uses ICU regex like CotEditorand keep in mind that KM does not enable the multiLine flag by default.

(You have to know the quirks of your tools.)