Help with editing a string with a number that adds up with each appearance


It would seem like a basic loop with a calc on the variable so that the following instances of the string gets updated.
I'm running KM on another computer so can't easily copy and paste so I will sum up here:

  1. Prompt for User input and add vars for episode, Scene and Number
  2. Read the specific text file to the System Clipboard
  3. Search and Replace System Clipboard using String
  • in my case the specific string is static
    and replace with the above variables %Variable%Episode%%Variable%Scene%%Calculate%Number+10%

So it finds and replaces all the instances of my specific string with the variables I set and adds 10 to each instance's number var. But I want it to loop and add 10 to the var and then write that value to the following string, ecetera.

I can't figure it out.

Various things in your text are unclear to others.

Search and Replace, for example, involves two strings, the pattern to find and the replacement.

The only way to get help is to show before and after examples.

1 Like

I understand. The first file is my export from Avid, the second is the result after I ran my macro.
So I can set the first part of the string but not get the number to add on by 10 correctly. Also it needs to keep the 4 digits. The search string will always be the same.

@ This file written with the Avid Caption plugin, version 1

01:00:20:12 01:00:23:22 PP_116_TST_0010

01:00:33:09 01:00:38:12

01:00:38:12 01:00:44:09

01:00:44:11 01:00:47:04

01:00:55:17 01:00:57:19

01:01:04:04 01:01:08:16

The end result should be:
@ This file written with the Avid Caption plugin, version 1

01:00:20:12 01:00:23:22 PP_106_621_20 ----- this needs to start at 0010

01:00:33:09 01:00:38:12
PP_106_621_20 ---- this then needs to calculate to 0020

01:00:38:12 01:00:44:09
PP_106_621_20 ---- 0030

01:00:44:11 01:00:47:04
PP_106_621_20 ---- 0040

01:00:55:17 01:00:57:19
PP_106_621_20 ---- 0050

01:01:04:04 01:01:08:16
PP_106_621_20 ---- 0060


Oops that first line needs to have a return after the timecode, my mistake.

01:00:20:12 01:00:23:22
PP_106_621_20 ----- this needs to start at 0010

OK, so as a diff (allowing for your amendment note – incidentally, you can always use the pencil icon to edit a post), something like this ?

PP_116_TST_0010 should change to PP_106_621_0010
The next instance should change to PP_106_621_0020, then PP_106_621_0030
and so forth.

Sorry, if I'm not clear.

And the start value (for the incrementing series) is supplied by the user,
or read from the first item of the source file ?

I input it as part of the Input prompt to set the variable at 0010 but it can also be read from the first item since it will always be that starting value.

I would personally tend to do this kind of thing with a script action, for example, if I have understood the ins and outs:

Search and replace with incremented numeric affix.kmmacros (6.6 KB)

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

    // main :: IO ()
    const main = () => {
            kme = Application("Keyboard Maestro Engine"),
            kmVar = kme.getvariable;

            source = kmVar("inFile"),
            label = kmVar("newPrefix"),
            width = kmVar("digitCount"),
            pairs = chunksOf(2)(
                lines(source).flatMap(x => {
                    const s = x.trim();

                    return Boolean(s) ? (
                    ) : [];

        return 0 < pairs.length ? (() => {
                firstPair = pairs[0],
                startValue = parseInt(

            return pairs.reduce(
                ([n, s], ab) => {
                        ns = `${n}`,
                        line2 = `${label}${ns.padStart(width, "0")}`;

                    return [
                        10 + n,
                [startValue, ""]
        })() : "No data found";

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

    // chunksOf :: Int -> [a] -> [[a]]
    const chunksOf = n => {
        // xs split into sublists of length n.
        // The last sublist will be short if n
        // does not evenly divide the length of xs .
        const go = xs => {
            const chunk = xs.slice(0, n);

            return Boolean(chunk.length) ? [
                chunk, ...go(xs.slice(n))
            ] : [];

        return go;

    // last :: [a] -> a
    const last = xs =>
        // The last item of a list.
        Boolean(xs.length) ? (
        ) : null;

    // 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();

Wow, I'll give it a try. That scripting is definitely above my abilities.

Thanks for the help.

Updated above – a typo had dropped the left padding with zeros to reach 4 digits.

I've been playing with it and getting close to the results I want. But the main action is definitely working. I just need to remove the first few lines, then add them back after the script, remove the last line and boom, I'm figuring it out. Thank you.

1 Like

For my own amusement and practice (because I'm sure @ComplexPoint's already provided a good answer)...

You have a list of {timecode, label} pairs. The label is a_b_c_d

You want to keep the timecodes as they are but change the label to v_x_y_z ---- position*10+(first d)-10, the final part padded to 4 numbers.

You have four "codes" but are only prompting for episode and scene -- I assume that's y and z? Is the "PP_106_" a constant then? Or is "PP" a constant and x=b-10, or user input?