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

I will give it a try. thanks

pbpaste | rev | cat -n | rev

Celver, but wouldn't that end up reversing the numbers?

So you'd get

…
line 01
line 11
line 21
line 31
…
2 Likes

I read about pbpaste but it's still not clear as to what it is doing.
When you say pasteboard, do you mean clipboard ?
Let's assume that I start off by selecting the text
Do I have to copy the text to the clipboard before running the shell script ?. Will the output of the script automatically paste, or should I add a paste action ?

Thank you for creating a new topic.

Your macro works perfectly. Thanks very much!

The macro is very useful to convert a table of contents to an alphabetical index.

1 Like

Thanks.

You don't need to use a test for CLIPBOARDSEED() since the KM Copy Action has that built in.
Also, you can just do the For Each on the Clipboard.

Here's how I'd write your Macro:

image

1 Like

I added this a the end for alphabetical sorting. Works fine.

The Perl scripts from the forum did not work.

Since I was a bit harsh on shell scripts above, let me now say that, IMO, there are a few use cases where a simple, canned, shell script can be the best solution. I have this one saved in my KMFAM collection, and it seems to work fine here:

image

If any of you shell script gurus care to comment or jump in, please do.

I would expect, but have not tested, that a simple shell script like this would be faster can calling a BBEdit Text Factory, but I could be wrong.

1 Like

UGH. Yes. How dumb of me to miss that. So this will work great… as long as you have fewer than 10 lines.

1 Like

Yes. The two terms are used interchangeably. I believe Keyboard Maestro uses clipboard but Apple (at least for pbpaste and pbcopy uses ‘pasteboard’).

Yes. pbpaste translates to “take what is on the clipboard/pasteboard and send it to output” so whatever you want to work on must already be on it.

You would need to tell the Keyboard Maestro “Execute Shell Script” action to "paste results” (or save results to a variable, or whatever else is suitable).

Note that, as Peter rightly pointed out, my solution only works for fewer than 10 lines.

If you want a simple shell-based solution, instead of mine, you should use Dr Drang’s suggestion.

Note that his uses pbcopy at the end which means “Save the result to the clipboard/pasteboard” so you would not have to tell Keyboard Maestro to do that.

1 Like

Following up @tjluoma's comment, the reason I have pbpaste and pbcopy in my script is that I was sitting in front of an iPad when I wrote the answer and forgot that Keyboard Maestro has options for dealing with the clipboard as input and output. This would be the better way:

If you're not worried about the possibility of having a numbered blank line at the end, awk is shorter:

You could, of course, surround this step with Copy and Paste actions to get a macro that replaces the selected text with the line-numbered version of it.

2 Likes

thanks

thank you for the explanations

1 Like

Thank you very much @JMichaelTX

I have a question for @JMichaelTX @drdrang @tjluoma @ComplexPoint

@JMichaelTX brings up an interesting point. In fact he opens a pandora's box, which is to use the simplest fastest tool for the task. In this case it is a one word shell script inside a KBM action.

For a novice, shell scripts are cryptic even though I went so far as to read the take control book on the subject.

In the example below @JMichaelTX uses a one word text transform shell script where I was struggling trying to figure out a regex.

Just as a start, I was wondering where I could find a repertory of very short shell scripts used for the many possible commonly used transformations of selected text. Just a few examples are adding quotes, title care, remove new line feed, remove blank lines, delete tabs, etc etc etc

thanks very much !

1 Like

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