Red Green Repeat Adventures of a Spec Driven Junkie

Saving Keystrokes: Replacing with Repetition

tl;dr There’s a way to replace each line that preserves part of the original line and allows repetition of parts of the original without having to retype everything. Jump to solution

I go over a way to replace parts of the text while maintaining the original AND allowing reuse of the original.

I encountered this problem when setting up configuration variables the wrong way and facing retyping thousands of characters (in CAPS!) I show you solutions and the solution I settled on.

You will learn a new way to replace text that can will be efficient, even when just replacing just two lines of text with repetition.

This article will take you about five minutes to read.

Rectangular Octave Virginal source and more information

Introduction

Ever write a bunch of variables for a configuration and find out later there were slightly wrong?

Not wrong as in toss out the whole thing. Wrong in that there just needs to be additional syntax around configuring variables.

Example

I was working with ansible configuration for setting environment variables based on external values:

- ENVIRONMENT
  - URL:            EXTERNAL_SYSTEM_URL
  - PORT:           EXTERNAL_SYSTEM_PORT
  - LOGIN_ENDPOINT: EXTERNAL_SYSTEM_LOGIN_ENDPOINT
  - HEADER_DETAILS: EXTERNAL_SYSTEM_HEADER_DETAILS
  - ...
  - VARIABLE:       EXTERNAL_SYSTEM_VARIABLE

The right way to setup these variables would be:

- ENVIRONMENT
  - VARIABLE: "{% if EXTERNAL_SYSTEM_VARIABLE is defined %} EXTERNAL_SYSTEM_VARIABLE {% else %} null {% endif %}"

Effectively, the change is:

# from
VARIABLE: EXTERNAL_VARIABLE
# to
VARIABLE: "{% if EXTERNAL_SYSTEM_VARIABLE is defined %} EXTERNAL_SYSTEM_VARIABLE {% else %} null {% endif %}"

If this change is for one line, there would be no article, right?

At the time, I set more than 20 variables in the former format that required a change into the latter format.

My fingers were already crying…

Possible Solutions

Hmm what are possible solutions to this problem? Surely there must be more than one way to solve this problem.

Just Start Over?

Use this as a valuable lesson in that it’s better to double check things are working with a small sample instead of committing ALL variables to the same format.

Retype the whole thing for each variable, n, that needs m characters.

An n x m lesson. :-)

In this case, it’s 92 characters per line, m = 92, with four variables, n = 4, this would require: 368 keystrokes.

Adding that these variables are in CAPS… ugh.

Copy Replace?

How about using copy-replace feature of an editor? A simple “copy replace” will work, for each line. That is surely better than just starting over.

Well, for every different VARIABLE value, I would have to type the input value to change (which would be the whole thing) and then typing out the whole new line.

Given the replacement is about 92 characters, and the input would be about 8 characters, each change requires typing 92 + 8 characters.

Effectively, typing out all the old value, a, AND the new value for each variable, m, for each line, n:

An n x (m + a) lesson - ouch!

In this case, doing a copy replace would require:

4 x (92 + 8) = 400 characters

Just starting over doesn’t look so bad now does it?

Note: Alliteration

What makes this problem even harder is, the line had one instance of the variable name, now it has two copies and each instance are in a different location.

Write a Custom Program?

If n is large, say: 20, which is what I was encountering with even longer EXTERNAL_VAR values, I was encountering at least 2000 character changes.

Even with ten fingers, that’s an average of 200 keys per finger.

It might be easier to write a quick script to do this change that is less than 2000 characters, isn’t it?

Definitely possible.

As much as I like this approach, I can’t help and think there’s an even better approach.

Solution: Less than m characters!

I found a solution that solves this problem that uses fewer than m characters for any amount of n?

I didn’t write a script and put it through a minimizer (although that’s a valid approach and good idea!)

If you want to pause here and see what you can do, I’ll wait.

Scroll down whenever you’re ready.

Jonny Gios - Shopping Center in Leeds, UK source and more information

My Solution

My solution to this problem is to write a program, in regex!

I find regex to be a great language for any kind of text manipulation. Knowing regex can help you save thousands of keystrokes and headaches.

In regex there’s an operator that allow accessing the original item in the match statement in the replacement statement.

To access the original item in the replacement statement is:

&

Yes, just that symbol is enough.

With this single character, regex effectively becomes a copy-replace system on steroids.

Solution to Original Problem

regex by itself isn’t sufficient, it does the heavy lifting. To make it work, I used sed, the stream editor with regex to solve the original problem:

 cat <file> | sed 's/{{VARIABLE.*}}/{% if & is defined %} & {% else %} null {% endif %}/' > <file>.tmp 

This effectively solves the original problem, with only 75 characters, which 75 < 92, a small saving. When adding in the whole shell statement, it’s 102 characters, which 102 > 92, so a slightly larger expense over the original.

This went from an n x m lesson to an m + 10 lesson.

My fingers were dancing m + 10 times!

The Real Win

This whole statement pays for itself when the number of variable to change, n is greater than… two?!

If there are just two variables you need to change, using this shell statement with regex is more efficient than starting over again.

Conclusion

Don’t underestimate the power of regex. In this case, it’s saved me thousands of characters being re-typed with just a single character: &.

This solution is simple enough that I will come back to it whenever I have to change more than two variables, which may often in the future.

Learn to love regex - your fingers will love you for it.