Insert Characters Within The Text in a Variable

Hi all

I want to change a variable that always consist of 8 numbers, like:
into this:

of course, i could split (substring) the variable three times, into three new variables, and then construct a new variable by combining the three. But there must be a more elegant quicker nicer way :slight_smile:

Very easy if you know Regex, using the KM Search and Replace action with the "Regular expression" option:

Search For:

Replace With:

Let us know if this works for you.

Ah! I knew it was that simple!
I didn't knew that there was a regex within search and REPLACE.

I would first think to do it like this:

but a non greedy version is even more elegant

In a real macro i would not search the text 12345678 of course, this is just an example.

In the future, please always provide real-world source text, and real-world example of desired results. This will save both of us a lot of time.

Please read:
Tip: How Do I Get The Best Answer in the Shortest Time?

Thanks, but this is NOT about using a non-greedy pattern.
It uses a positive look-ahead to require that one digit always follows the first two digits.

You've already been given a good solution there : -)

In case others come to this thread with contexts in which Keyboard Maestro Execute Script actions might be helpful, chunksOf (length N) is, as you intuit, a commonly needed pattern, which you can use to:

  • chunk a string or list into pieces of equal length (perhaps with a shorter one at the end, if the division has a remainder),
  • and rejoin the chunks by intercalating some new filler value

So for example, with Keyboard Maestro Execute Script actions, given a definition of chunksOf(n) for JavaScript, AppleScript, or Python, expressions like:


    Application('Keyboard Maestro Engine')


tell application "Keyboard Maestro Engine" to ¬
    set sampleString to getvariable "sampleString"

intercalate(":", chunksOf(2, sampleString))



As in:

Chunks of length N.kmmacros (22.4 KB)

JS Source
(() => {
    'use strict';

    // --------------- CHUNKS OF LENGTH N ----------------

    const main = () =>
            Application('Keyboard Maestro Engine')

    // --------------------- 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 0 < chunk.length ? (
            ) : [];
        return go;

    // MAIN ---
    return main();
AppleScript Source
on run
	tell application "Keyboard Maestro Engine" to ¬
		set sampleString to getvariable "sampleString"
	intercalate(":", chunksOf(2, sampleString))
end run

------------------------- GENERIC ------------------------

-- chunksOf :: Int -> [a] -> [[a]]
on chunksOf(k, xs)
		on go(ys)
			set ab to splitAt(k, ys)
			set a to item 1 of ab
			if {} ≠ a then
				{a} & go(item 2 of ab)
			end if
		end go
	end script
	result's go(xs)
end chunksOf

-- intercalate :: String -> [String] -> String
on intercalate(delim, xs)
	set {dlm, my text item delimiters} to ¬
		{my text item delimiters, delim}
	set s to xs as text
	set my text item delimiters to dlm
end intercalate

-- splitAt :: Int -> [a] -> ([a], [a])
on splitAt(n, xs)
	if n > 0 and n < length of xs then
		if class of xs is text then
			{items 1 thru n of xs as text, ¬
				items (n + 1) thru -1 of xs as text}
			{items 1 thru n of xs, items (n + 1) thru -1 of xs}
		end if
		if n < 1 then
			{{}, xs}
			{xs, {}}
		end if
	end if
end splitAt
Python Source for Execute Shell Script
/usr/local/bin/python3 <<PY_END 2>/dev/null

'''Chunks of length N (for strings and lists)'''

# ------------------------- TEST -------------------------
# main :: IO ()
def main():
    '''Chunks of N'''
# ----------------------- GENERIC ------------------------
# chunksOf :: Int -> [a] -> [[a]]
def chunksOf(n):
    '''A series of lists of length n, subdividing the
       contents of xs. Where the length of xs is not evenly
       divible, the final list will be shorter than n.
    def go(xs):
        return (
            xs[i:n + i] for i in range(0, len(xs), n)
        ) if 0 < n else None
    return go

# MAIN ---
if __name__ == '__main__':
1 Like

fantastic complexpoint!