This Is A Blog

There are millions like it, but this one is mine.

Editing Without an Editor

It doesn't happen often, but it does happen.

You've logged into a machine - or container, more likely - with a very minimal base system that doesn't include any text editors. Not nano or even ed.

But you really need to make just a couple changes to a file or two, and spinning an entirely new image & reploying is such a P.I.T.A. Maybe it's worse: you can't respin and redeploy lest you destroy important state. What to do!?

It won't be fast - you'll be changing one line at a time - but you can make this work.

The key is a scripting language interpreter, ideally perl - that's what we're using here - but the method works with any that allow scripts passed on the command-line. I've yet to meet a base image without at least one of perl or python: their role as "system" languages tends to make their presence a requirement.

Inserting lines

  1. Locate the line in the file you'd like to change, then note the contents of the line immediately after it. Let's call this <LINE_POST> from now on.
  2. Run the following, importantly redirecting to a temporary file first so as not to complete clear the file contents! In this example, the inserted text is refered to as <INSERTED>:
$ perl -n -e 'print "<INSERTED>\n", if (/<LINE_POST>/); print;' the-file-to-edit > /tmp/some-temp-file-name
$ mv /tmp/some-temp-file-name the-file-to-edit

What's going on here?

The -n -e options tell perl to:

  • "assume while (<>) { ... } loop around program" (-n)
    • the <> "diamond operator" reads the lines of files provided on the command-line (or STDIN) until none remain
      • in this case it is reading the contents of the-file-to-edit
  • to run the string provided as the argument to -e as a one-line program

The code we've given -e:

  • searches for the <LINE_POST> line and if found, prints the line-to-insert before it:
    • print "<INSERTED>\n", if (/<LINE_POST>/);
  • prints all current lines in the file: print;

(Note: this small code makes heavy use of the implicit variable $_ to be even smaller: for example, the logic clauses here are written in full as $_ =~ /.../)

Removing lines

Changing the logic just a bit to not print a given line (let's call that <LINE_TO_RM> here) and viola you can now remove lines from the file as well:

$ perl -n -e 'print, unless (/<LINE_TO_RM>/);' the-file-to-edit > /tmp/some-temp-file-name
$ mv /tmp/some-temp-file-name the-file-to-edit

(taking advantage of perl's lovely & rare unless keyword)

You may never need this technique - I hope you don't! - but if you do, it's an absolute life-saver.

Happy New Year, Earth! 🥳