Capture the Years using Regex

I am trying to capture the two years from a data string that may be formatted in any of the following ways.

23 July 1914 - 11 July 2002
1914 - 2002
abt 1914 - abt 2002

The year will always be a 4 digit number. The last year will always be there but the first one may or may not be present.

I would like to use Regex just so that I can learn Regex but if there is a better way using just KM that would help.


Lot of approaches – here's one.

If you combine regular expressions with some scripting, you can use a handful of simpler regex.

For example:

  • Line break [\r\n]+
  • Word break \s+
  • Four digits \d{4}

Here, capturing each year paired with a (one-based) line number.

Dates in numbered lines.kmmacros (5.4 KB)

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

    const main = () => {
        const rgxYear = /\d{4}/gu;

            kme = Application("Keyboard Maestro Engine"),
            sampleText = kme.getvariable("sampleText");

        return JSON.stringify(
                (lineString, iLine) => words(lineString)
                    wordString => rgxYear.test(wordString) ? (
                            [1 + iLine, wordString]
                    ) : [])
            ), null, 2

    // --------------------- 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 ? (
        ) : [];

    // words :: String -> [String]
    const words = s =>
        // List of space-delimited sub-strings.

    return main();

How about:

cc's response below is very valid, and now that I've woken up, I see that my response misses one of your requirements about cases where there's only one variable. I could fix my response easily enough if you want me to. Here's the fix: (make sure you turn off error flags for the first Search macro.)

Bear in mind that something is incomplete about your request, because you didn't ask for me to indicate "how many results were returned." So I'm not sure how you can make this work for you.

Hey Roger,

You're not being clear about the desired output.

Your string has 7 substrings displaying a year.

You want to capture each one of those 7?

You want to place each one (even the duplicates) in a different variable?

Will there always be 7 dates, or will the macro need to dynamically create variables for a variable number of year strings?


There can be only 2 returns. Your suggestion has worked great.


If you are happy, I'm happy.

I'm Happy