Search and Replace Issue

Hey All!

Having an issue with a search and replace action. I have a long list of folder paths that I have stored in a text file, and wish to go through that list and remove lines that contain a specific string.

I made the following macro and ran it.

However, the macro only partially deleted the lines that contain the target string.

Resulting in lots of lines that look like the second line below.

/Volumes/cloud/Active Projects/040722_BENJAMIN_MOORE/_deliverables/56462_030422_BENJAMIN_MOORE/Lights 30 030422 6pm
/Accenture_Foresight_Radio_Opt 2_083122

When I modify to macro to run on the system clipboard, and copy a few lines, I get the same result. However, when I copy and paste a few test lines into a "Set Variable to text" action, and run the macro on that variable, it works and fully removes the lines containing the target string. My assumption is that there is something happening regarding non printable characters here that I am not aware of, but I'm stumped!

Difficult to tell without seeing some actual input and output -- what did the "second line below" look like before processing?

But you could also try either of the approaches below, which might get round whatever the problem is and will also be more efficient than iterating through a collection of lines. (It's also worth noting that you can use KM's "Search and Replace" directly on a file, and even create a new file with the output, rather than read into then write out variables.)

The simplest way to do this is in KM is a regular expression "Search and Replace" followed by another S'n'R to remove the now blank lines:

Delete Lines Test.kmmacros (3.6 KB)

Image

The quickest (probably...) way to do this is with an "Execute Shell Script" and grep -v -- the -v means "return all lines that don't include the string":

Delete Lines Shell Test.kmmacros (3.1 KB)

Image

That one lets you set the file paths and search string as KM variables (and you could replace those with prompts), which makes the macro more long-winded. You could hard-code everything in the "Shell" action for a one-action macro.

1 Like

Hey Evan,

Three things...

  1. When asking for help like this please post the simplest possible testable macro.
    • This provides much more (and vital) information to potential helpers than you realize.
    • It saves people time and trouble and improves the likelihood that you'll get timely and useful assistance.
  2. Please review this: Tip: How Do I Get The Best Answer in the Shortest Time?
  3. This particular task is one where I'd just open the file in BBEdit and get the job done in a few seconds.
I recommend BBEdit because…
  • Although BBEdit is a commercial product, the trial version reverts to a
    still very powerful and free (BBEdit-Lite) version after 30 days.
  • It is very Mac-like.
  • It has excellent support for RegEx.
  • It is very AppleScriptable.
  • It has a two versatile command line tools.
  • It has been in continuous development for over 25 years.

Take Care,
Chris

(Keyboard Maestro Moderator)

Thanks Chris.

Here's a macro that illustrates the issue i'm running into.

Clear Lines.kmmacros (6.0 KB)

Unfortunately I'm still running 10.14.6 so I can't use BBEdit, but i'll check it out once I upgrade my OS (soon).

1 Like

Then grab v14.1.2 from the Downloads page.

1 Like

Running the grep command does the trick. Thank you so much. Will explore this other option too and see if i can suss out what was the problem.

Hey Evan,

This is a perfect example of what I was saying about posting a real world sample macro.

In your data was one line with a carriage return instead of a linefeed, and that can cause all sorts of head-scratching problems...

To fix that I used a Unix-line-endings filter.

Note that I've transformed your variables into local variables.

Global variables are persistent and inevitably come back to bite, unless you manage them very carefully.

You also were finding and replacing in the line variable, and that is NOT part of your data set.

To simplify I removed the find/replace and used a separate variable to collate only the lines that didn't contain the search string.

In general I would take a similar approach to what @Nige_S did when tackling this task with Keyboard Maestro, although I might have used perl instead of sed if I went the shell route.

In any case – take a look at the new macro just to see how it works – it's pretty simple.

-Chris


Clear Lines.ccs v1.00.kmmacros (6.8 KB)

Macro Image

Keyboard Maestro Export

Just for giggles here's another method using a simple AppleScript filter.

Clear Lines.ccs v2.00 (AppleScript).kmmacros (8.9 KB)

Macro Image

Keyboard Maestro Export

Now let's take Nige's regex macro and use what we've learned about the problems involved in this task.

I've also simplified the regex a bit.


Clear Lines.ccs v3.00 (RegEx).kmmacros (8.8 KB)

Macro Image

Keyboard Maestro Export

Thank you both for all your generous help and insight. It's much appreciated.

Chris,

I don't think this is the root cause of the problem -- "For Each" is line-ending agnostic. Consider the following, using @Evan_Mangiamele's original text (which you'll see in BBEdit still has the CR in it), and counting the "For Each" loops:

Clear Lines Counter.kmmacros (5.4 KB)

Image

Instead, I think it's a logic problem. @Evan_Mangiamele -- consider the following text:

/Volumes/cloud/Active Projects/040722_BENJAMIN_MOORE/_Archived Items/_deliverables/56920_041322_BENJAMIN_MOORE
/Volumes/cloud/Active Projects/040722_BENJAMIN_MOORE/_Archived Items/_deliverables/56920_041322_BENJAMIN_MOORE/VO

On the first run through your "For Each" loop you grab the first line of the above and use that as your search term in the search and replace. But you've set search and replace to "All matches" and there aren't start- and end-of-line anchors -- in this case the first line is a match and is deleted and the majority of the second line is also matched and deleted. Visually:

/Volumes/cloud/Active Projects/040722_BENJAMIN_MOORE/_Archived Items/_deliverables/56920_041322_BENJAMIN_MOORE
/Volumes/cloud/Active Projects/040722_BENJAMIN_MOORE/_Archived Items/_deliverables/56920_041322_BENJAMIN_MOORE
/VO

So after only one loop your text is

/VO

...which is what you were seeing in your original macro (see demo macro below). You can actually fix it by setting the "Search and Replace" to "First Match" (although you then get left with empty lines).

Interesting side note from all this -- it appears that items for use in the "For Each" are gathered before any processing occurs. If you delete all or part of a line from the Collection before "For Each" gets there it will still be used. Check the text windows in this:

Clear Lines copy copy.kmmacros (8.8 KB)

Image

Ah! @Nige_S THIS makes much more sense to me, and I recognize my error now.

Good to know that the "For Each" behaves in that way.

Again, really appreciate ya'lls insight on this, it's immensely helpful for learning.

Also! I tried BBEdit, and wow, this was super easy to do there. Seems like a great tool for the toolbox and I'll definitely be purchasing it. Thanks for the recommendation

Thanks @Nige_S – I didn't realize that...

Nevertheless – mixed and matched line endings can cause a world of hurt. I've spent many hours debugging that kind of thing in various contexts.

Pesky invisible characters that your trusted text editor didn't display in the way you thought it should...

BBEdit grew up on CRs, and the switch to LFs has a glaring oddity.

\r and \n are treated the same by BBEdit's RegEx as LFs, although everywhere else on the planet Earth they are quite distinct.

To search explicitly for CR you must use a Hex or Unicode form:

\x{000D}

I kept an old JAVA based text editor around, until it died – because it beautifully and distinctly displayed line endings. These days keep a copy of TextMate around for that, and I also have a robust Hex Viewer/Editor Synalyze It! Pro!

There's a lite version on the App-Store:

Must admit, I liked it like that. One less thing to think about in the "old days" when you never knew if text had come from OS 9 or X or an out of date app that ran on X but still used CRs.

One of the first things I still do when there's a text problem is to open the file in BBEdit, check the line count, then "Normalize Line Endings" and check the count again...

The one that still catches me out is when you paste a string with mixed CRs and LFs into Script Editor and it auto-converts for you. Does Script Debugger do that too?

Yep. That's one of BBEdit's very handy features.

You can also Zap Gremlins and Hex-Dump a document.

This is occasionally a gotcha when moving between them.

I have a custom Zap-Gremlins script for Script Debugger that helps in such situations.

1 Like