Reverse Word Order of Lines in the Clipboard

I get an error on this line:

set components to ca's NSPersonNameComponentsFormatter's new()'s ¬
    personNameComponentsFromString:strName

error "-[NSPersonNameComponentsFormatter personNameComponentsFromString:]: unrecognized selector sent to instance 0x7fb16ac72b70" number -10000

running Script Editor 2.8.1 (183.1) on macOS 10.11.6

Thanks for sharing. Do you have an example of how to use these handlers?

Since there are two of us compiling this list of names we may have duplicates. What can be added to look for duplicates and leave the list with only a single incident of name?

Fortunately, this is much easier than you might think. Since you're already using the Unix sort command to alphabetize the names, all you have to do is add a space and -u (the "unique" flag") after it to remove any duplicates:


5 Likes

You're making my job easy! Thanks and Happy Holidays!

2 Likes

Gabe, thanks for sharing the Unix sort command.
I'm not a huge fan of shell scripts, but the simplicity of this make it well worth remembering/using.

While sorting and eliminating dups can be done in both AppleScript and JXA, they require considerably more code (of course, @ccstone will probably prove me wrong. :wink: ).

This is very readable and very easy to use.
I'm adding it to my KMFAM.

1 Like

You’re very welcome! I’m right there with you when it comes to shell scripts, but the sort command, and a few of its flags like -n for sorting numerically (i.e. putting 10 after 2 where it belongs instead of before just because it starts with “1”), -r for sorting in reverse, and of course -u, is an exception to the rule. Even then, I wouldn’t generally think to make use of it if @peternlewis hadn’t made the great call to add input options to the Execute a Shell Script command in KM8 that make it so much easier to work with the exact text you want. In lieu of KM having built-in filters for this kind of sorting and duplicate processing, this is truly the next best thing.

2 Likes

Hey JM,

There are many shell commands just like that — powerful and concise. That's why I decided to learn at least the basics of shell scripting 8 or 9 years ago.

True.

AppleScriptObjC is not as concise as sort, but it's really not bad at all:

------------------------------------------------------------------------------
# Auth: Christopher Stone { Heavy Lifting by Shane Stanley }
# dCre: 2017/11/22 10:55
# dMod: 2017/11/22 10:57
# Appl: AppleScriptObjC
# Task: Sort a list of type text and remove duplicates.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @ccstone, @ASObjC, @Sort, @List, @Remove, @Duplicates
------------------------------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
------------------------------------------------------------------------------

set theList to {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "two"}

set sortedUniqueList to SortAndMakeUniqueArray(theList)

------------------------------------------------------------------------------
--» HANDLERS
------------------------------------------------------------------------------
on SortAndMakeUniqueArray(anArray)
   set theSet to current application's NSSet's setWithArray:anArray
   set anArray to theSet's allObjects()
   return (anArray's sortedArrayUsingSelector:"compare:") as list
end SortAndMakeUniqueArray
------------------------------------------------------------------------------

Then of course there's the Satimage.osax:

set theList to {"One", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "two"}
set sortedUniqueList to sortlist theList comparison 1 with remove duplicates

--> {"eight", "five", "four", "nine", "One", "seven", "six", "ten", "three", "two"}

Comparison 1 makes the sort case-insensitive.

-Chris

3 Likes

I, too, am very inexperienced with Regex (and AppleScript, and perl). But I am skilled with shell commands. So I have an alternative using only shell commands. Feel free to ignore this post, I just like making solutions using the shell. About 33% of the shell command below I found online, the remainder was my own creation.

Here's a little bit of AWK.

-Chris


Awk -- Reverse FirstName and LastName.kmmacros (4.9 KB)

I'm always happy when someone comes up with a new, simpler solution. Especially when that person is me. I have a totally different idea that requires no code. Just a simple shell script. Pipe your text into this:

rev | sed 's/$/ ~/' | tr ' ' '\n' | rev | tr '\n' ' ' | tr '~' '\n'

This assumes you don't use the character '~' in your file. I could not find this trick anywhere on the internet so I should score 100 points for this unique solution. I think I should be allowed a little pomposity for coming up with this idea. You can also use a similar, simpler technique to reverse the lines of a file, which I also came up with today, and nobody on the various sites on the internet had this idea either.

rev | tr '\n' '~' | rev | tr '~' '\n'

Oh, there's an extra space at the beginning of most of the results for the first command above. but I'm sure you can figure out how to fix that if you need it fixed.

Do you not consider shell scripts to be code? I wouldn’t categorise them as prose.

When you have time, could you briefly run through what these shell snippets are doing ?

1 Like

Hey @Sleepy,

As far as I can see your code does not perform the job the OP (@slyfox) requested – which was to reverse the name order of lines from input.

John Smith

Becomes:

Smith, John

Simple Sed:

Reverse Name Order of Each Line of Input (Sed).kmmacros (1.9 KB)

Simple Awk:

Reverse Name Order of Each Line of Input (Awk - Simple).kmmacros (1.9 KB)

My original Awk script handles any number of words per line, but this more simple script is tailored to exactly reverse first-name and last-name.

Simple Perl:

Reverse Name Order of Each Line of Input (Perl - Simple).kmmacros (1.9 KB)

-Chris

Since the word "code" seems to be causing a distraction, I drop that claim. Just judge my solution by its simplicity and uniqueness. In my solution you don't see IFs, THENs, LOOPs, or FUNCTIONs, which some of the solutions clearly show. Obviously there's loops required within the rev command to implement it, but it's hidden from the user.

Rev reverses the characters in each line. Tr translates the first character to the second character. \n is the newline character.

Let's look at the second snippet. Step 1. Reverse each line in the file. Step 2. replace all CR's by "~". Step 3. Reverse all the characters in the single merged line. Step 4. Put the CR's back. That reverses the lines in the file perfectly. Pipe any file into that and you will see it reverses the lines. It worked for me in a Terminal command window.

The other one is a bit more complex and I see CJK is refuting that it works so I will answer his question separately.

I think you're saying my solution doesn't work because it doesn't have a comma in the result. It's hard to tell what you're saying because you don't say why you object to my solution. All you say is that "it doesn't perform the job". I'm going to have to guess why you are objecting to my solution, and I'm guessing that you are objecting due to the lack of a comma. Or maybe you are objecting because I didn't use the clipboard.

Therefore, you win. I didn't use the clipboard and I didn't insert a comma. To be honest, I just didn't think those elements of the OP's questions were important or part of what the OP was really trying to solve. And it sounded to me like the OP could handle those things on his own. Maybe I was wrong.

You also put the word code in italics, which tells me you object to me using that word. Okay I retract that word since it's making everyone object today. Just judge my "code" on its simplicity and beauty.

Since I can't be sure why you are objecting to my solution, I'll show you what my solution actually does. This looks to me like it's reversing the names. If you look closely you will see a leading space on lines 2 & 3. In my mind I didn't think that would be a problem for the OP. Just like you didn't use the clipboard in your three solutions because you didn't think that was the problem, even though the OP stated the clipboard clearly.

> cat file1 | rev | sed 's/$/ ~/' | tr ' ' '\n' | rev | tr '\n' ' ' | tr '~' '\n'
> Washington George 
>  Lincoln Abraham 
>  Rosevelt Teddy 

These are the results. They stand for themselves. The names are reversed. But you are right my solution fails on many counts:

  1. My solution is "code" even though I claimed it wasn't.
  2. My solution failed because it didn't generate a comma.
  3. My solution failed because it generated a leading space.
  4. My solution failed because it didn't post the result in the clipboard.

If any website moderator wants to delete my posts because my solution "doesn't perform the job", that's okay with me and I won't complain ever.

Hey @Sleepy,

My mistake, this code does work, although the names are not delimited by comma-space.

echo "$dataStr" | rev | sed 's/$/ ~/' | tr ' ' '\n' | rev | tr '\n' ' ' | tr '~' '\n'

I tested in a BBEdit Shell Worksheet and somehow the first pass failed. (I assume a user-error of some kind.)

-Chris

Oh, it looks like our posts crossed in the mail. That's unfortunate. That would have cut down my response quite a bit if I had seen your last post first.

Try and get into the habit of doing this as standard practice. Whenever you post a solution such as the ones you did, it is really helpful (especially to those who don't script) to have a brief run down of what is happening, and then an example of it in action, with the input, the implementation if required, and then the result.

When you explained to me step-by-step what was happening, it was a lot clearer for me.

Yup. I gave it a try and it worked. It's a creative solution. I'm pretty impressed at the idea behind it and it certainly isn't something I would have thought up. It does, as you said, preclude one from having a tilde appear in the file, but I presume the tilde in the command expression can be replaced with any character, provided it doesn't appear in the file ?

Did you know you can do this to reverse the order of lines in a file:

tail -r /path/to/file.ext

I can sense that you felt perhaps personally slighted, and possibly dismissed by the (incorrect) conclusion that was made about your first shell snippet. I can empathise, as I'm sensitive as well and often interpret things negatively at first. But you're going to get feedback when you submit anything, and it won't always be good. Just don't let it discourage you from submitting more, as I for one quite enjoy your unique way of problem-solving so hope to see more. Try not to get defensive, though. We all sound a lot more abrupt and matter-of-fact when we type, and it's easy to misconstrue brevity or a formal tone as an insult or rudeness. I don't know where you're from, but I find I'm always pissing off Americans for some reason, and think it's my Britishness that favours being indirect in how I say things (which we are raised to view as politeness), whereas I sometimes feel jolted by the directness that Americans seem to favour, and then remember they're not being aggressive, they're just being American.

Anyway, I'm looking forward to your next lightbulb and unique solution.

1 Like

That's a very kind and generous post. You could be a psychologist with that kind of thinking. You were probably pretty accurate in your analysis. Although it has always been one of my techniques in life to criticize myself online, that way when people try to disagree with me they are agreeing with me. :slight_smile: And sometimes it works.

You are right about the tail -r, and I came across that during my research to do word reversals. But the real reason I mentioned it, I think, was because it was a stepping stone to achieving the new method I developed for reversing words in lines. I thought it would benefit people to understanding how my word reversal filters worked. I think that's why I mentioned it.

But a lot of solutions to these problems ended up using commands and parameters that simply aren't available in macOS. My solution uses only the most basic functionality in rev, tr, and sed. In fact you have no idea how hard it was for me to work around the bug in macOS that this doesn't work:

sed 's/\n/~/'

From what I can see macOS is the only version of UNIX that doesn't recognize \n as a search code in sed. That probably took me an hour to work around.

P.S. I'm Canadian. I don't reveal more than that about myself however.

Thanks. The next one that I planned to post was a dozen or so Macros that implement all the functions that one does with "sets", like set intersections and unions, and cross-products, using the lines of a text variable as the members of the set. But I got a little distracted with all these other posts today.

1 Like