How Do I Add Line Numbers to End of Each Line? (useful to convert a table of contents to an alphabetical index)

There are various resources with names like this:

[Bash-Oneliner](https://github.com/onceupon/Bash-Oneliner)

(in which the Variable section might be a starting point)

1 Like

Thanks. I've often been there, but generally try to avoid her.
:wink:

There are lots of good examples right here in the KM Forum.
Maybe each of the Shell Script gurus could put together a list of their best, most useful scripts, and post as a separate topic in the Macro section.

Here is my list of Shell Scripts that I have found useful:

Useful Shell Scripts [Example]

:sunglasses:

I've been bitten by that one – sadly, more than once...

So I built a default test set for Typinator to make sure I always test with at least 2 digits.

read -r -d '' dataStr <<'EOF'
One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Ten
Eleven
Twelve
Thirteen
Fourteen
Fifteen
Sixteen
Seventeen
Eighteen
Nineteen
Twenty
EOF

I usually prototype shell scripts in a BBEdit Shell Worksheet, so this format is convenient for me.

-Chris

1 Like

Hey Folks,

@drdrang gets the tersification award for his Awk script.  :sunglasses:

It's even quite readable if you know a little Awk.

I love terse little scripts that do a task well and are still readable.

Drang does mention his script will number blank lines, so you have to know your input data is clean.

The only certain sure way to do that is to make sure by massaging it (preprocessing) before processing it – or by conditionally processing it.


The input data in the following action has a mixture of empty lines, lines with spaces and/or tabs and/or non-breaking-spaces, and lines with usable data.

I'm removing the blank lines with Sed before moving on to number them with Awk.

Execute a Shell Script.kmactions (921 B)

If I was going to make this more bombproof I'd also strip any possible horizontal whitespace from the end of the data lines before numbering them.

When people type on a keyboard they often add a space to the end of lines inadvertently before hitting the return key, and there are plenty of other ways whitespace can infiltrate lines of data.

So – for any text processing job I find it wise to proactively treat the text. That's quite often much easier than pure conditional processing.


In this macro I'm doing some lightweight conditional processing and trying for fun to come up with a more terse line of Perl than Drang's that still does the job.

es … Execute Shell Script … Test 01.kmmacros (5.4 KB)

This kind of thing is great for getting work done on the fly, but for something to be used regularly I prefer a more formally written script:

Append Line Numbers ⇢ Perl v2.00.kmmacros (5.8 KB)

This is easier to read and improve upon.

Keyboard Maestro can do all of this this quite easily with native actions, and most folks will find the KM learning curve less steep than the Perl learning curve.

Nevertheless – the more you learn the easier it is to get work like this done – no matter what approach you take.

-Chris

1 Like

A footnote to all of this – much as I love the shell and have done for 40 years now :-), I suspect that it sucks an inordinate amount of fiddling and debugging time out of us all.

The "everything is a string" architecture soon charges (with interest) in debugging and pondering time what it gives in flexibility.

To some extent Keyboard Maestro inevitably shares that architecture – KM variables are all strings – but KM does at least create a separate run-time number type for calculations, and helpfully warns us when we try to do the right kind of thing in the wrong kind of field.

There are some attempts to ease and speed up the testing and refactoring of shell scripts in general, by offering richer types and more eloquent error messages, see for example, Shelly and Turtle:

[Haskell for shell scripting](https://www.haskellforall.com/2015/01/use-haskell-for-shell-scripting.html)

but they require an additional layer of setting up, and language-learning.

1 Like

Hey Rob,

I'm more likely to spend my time improving my understanding of Perl, Python, and JavaScript, but this is interesting.

Thanks.

-Chris

Perl I've essentially put aside these days – too write-only when it comes to refactoring six months later, and the Python libraries are so rich now that incentives to use Perl seem rarer and less compelling than they used to.

Experimenting with a bit of Haskell (essentially the use of math as a programming idiom) yields shorter scripting time (fewer bugs, more code reuse, a methodology for problem solving, and easier refactoring) in both Python and JavaScript.

I think this repays itself pretty quickly, in various ways:

[Haskell for Mac IDE](http://haskellformac.com/)

The Haskell abstractions, because they are essentially just math, are always transferable to other languages, and map directly onto:

  • Array methods in JS like .map, .filter, .reduce, .flatMap, .some, .every etc etc),
  • and the itertools module in Python (in the documentation of which you will find acknowledgement of the debt to Haskell and related languages).
1 Like