Removing all symbols until there is a letter

Hey There!

I need to create a RegEx that will remove everything at the start of the line until there is any letter.

Example of a sentence below.

What you start with :
.21 _*. This is a random text

What you get after using the search and replace :
This is a random text

I've been trying to figure it out for some time now but I weren't able to come up with a good solution.

Not sure this is useful since you're asking for a regular expression.

Nevertheless, here is a Haskell Script that attempts to solve your problem. It only uses one higher-order function: dropWhile applied to the predicate not . isAlpha, that is dropWhile (not . isAlpha). In words, the function "drops" characters while an alphabetic character is not found.

Removing all symbols until there is a letter.kmmacros (3.8 KB)

Expand disclosure triangle to view Haskell Source
module Main where

import Data.Char

interact' :: (String -> String) -> IO ()
interact' f = putStr . f =<< readFile =<< getContents

main :: IO ()
main = interact' $ dropWhile (not . isAlpha)
1 Like

In terms of regular expressions, perhaps you can define a non-alphabetic prefix as something like:

Structure.kmmacros (3.1 KB)

Hey, I've tried to use the thing that you've sent me but i had trouble with your plugin.
After dragging it onto the Keyboard Maestro in the toolbar and running the macro it was saying "Plug in failed with script error"

Do you have the pre-requisites in the comment ?

Your solution worked quite well but i have a lot of lines with those sentences and the RegEx only applies to the start. Do you have any ideas on how to make it to transform more lines at a time?

I've downloaded a zip file from this site Execute a Haskell Script with Arguments - #2 by unlocked2412 , it was a version 0.03 and i dragged it onto the KM icon in the toolbar.

Good. That's it. So, you are only missing runhaskell program. I will make that clear in the comment. You must install Haskell to use my macro.

If you have homebrew, you can install with:

brew install ghc

By the way, Haskell is a fantastic (and useful) language to learn. It's takes little time to modify the code to operate on many lines, for example.

In that context I would personally prefer to take @unlocked2412's lead and use a scripting language, rather than a regular expression.

Here's a JavaScript variant, using Keyboard Maestro's built-in Execute JavaScript for Automation action.

Non alphabetic line prefixes pruned.kmmacros (4.1 KB)

Expand disclosure triangle to view JS Source
(() => {
    "use strict";

    const main = () =>
            Application("Keyboard Maestro Engine")
        .map(x => {
            const i = [...x].findIndex(isAlpha);

            return -1 !== i ? (
            ) : x;

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

    // isAlpha :: Char -> Bool
    const isAlpha = c =>

    // lines :: String -> [String]
    const lines = s =>
        // A list of strings derived from a single string
        // which is delimited by \n or by \r\n or \r.
        Boolean(s.length) ? (
        ) : [];

    // MAIN ---
    return main();
1 Like

Adding to @ComplexPoint's fantastic answer, here is a Haskell solution:

Removing all symbols until there is a letter.kmmacros (5.2 KB)

It worked really well, thank you for your help!

Thanks for your help also but it was a bit easier to use the method without the need to use homebrew and installing some plugins.

Yes, of course. You are welcome. In any case, Haskell Platform is a good addition to any machine :slight_smile:

I may be being exceedingly dumb here (and/or missing the point!), but couldn't you use KM's "Search and Replace" with a regular expression of "from the start of each line, find the longest match of non-alphabetic characters and replace them with an empty string"?

So your match expression would be (?m)^[^a-zA-Z]* and your "replace with" would be left blank.

Using sed in a Shell Script action should also do the trick: sed 's/^[^a-zA-Z]*//'.


I had the same thought @Nige_S but you beat me to it. So nice one!

Just to prove the point, here are a couple of actions that do the job:

KM 0 2022-04-10_22-44-11

with the end result being:

KM 1 2022-04-10_22-46-42

1 Like