Scripting a Find, then doing a second Find, searching in the first Find's results

47 views
Skip to first unread message

ChristianBoyce

unread,
Feb 16, 2023, 11:15:19 PM2/16/23
to BBEdit Talk
Hi there. I have a big bunch of text, marked up with codes that get replaced with fancy HTML stuff in BBEdit. I’m doing it with AppleScripts that do “replace” operations. Everything is great except for one new situation.

Normally, we select some text, and run a script to operate on the selection. So I can write things like this:

replace the_search_string using the_replace_string searching in selection of text window 1 of myDocument  options {search mode:literal, starting at top:true, wrap around:false, backwards:false, case sensitive:false, match words:false, extend selection:false}

In my new situation, I want to replace spaces with %20 but only in PART of the selected text. I have text like this:

[Joe J. Smith]<j...@joesmith.com><subject=Sign me up!><body=I want to subscribe to the newsletter.>

(There would be hundreds of lines of text selected, with various email addresses and “subject=“ text. Maybe 1 percent of the selected text contains text that I want to change)

Here, I want to change “subject=Sign me up!” to “subject=Sign%20me%20up!”

I can’t do this:

replace " " using "%20" searching in selection of text window 1 of myDocument

… because that would change “Joe J. Smith” to “Joe%20J%20Smith” (among other things. There is a lot of text in the selection that should retain its spaces rather than convert to %20.

What I want to do is (somehow) do a Find (searching in the original selection), looking for “subject=“ and then some GREP to get everything up to the closing “>”. I was hoping that by adding “with selecting match” I could select EVERY matching string (a discontiguous selection) and then search in this new selection for spaces and replace them all in one move with %20. Basically I’m trying to change the selection to be only the parts I want to make changes in.

My problem is, when I do a Find and “with selecting match” it only finds and selects the FIRST instance. I can then do my replacing within that text, but that only changes the first instance. What I’m doing now is looping through the document, changing the first instance that the Find finds, and then coming around on the loop to pick up the next one, and the next one, etc. It’s a little on the slow side and I have to set the number of loops to something pretty high to be sure I cover the most extreme situation (which is hard to predict so I am doing 1000 loops). A modification would be to figure out how many loops I have to make, which I think I could do, but I don't want to loop at all.

I know I can do a Find manually in BBEdit and choose the Find All option. Can I make use of the results of a Find All in a script? Maybe do a Find… with a Find All option, and then do my replace on the results of that Find?

Maybe my approach is all wrong here. Even if it is, it would be useful to know whether I can do a Find… to create a discontiguous selection. If I can, my problem goes away— I do a Find... within the original selection, I select the results box that Find... (producing a new, smaller selection), I run a single “replace” on that new selection. If I can’t do that, I wonder what is the right way to go.

Thanks for any assistance you can give. Basically I'm trying to get out of doing a loop.


Christopher Stone

unread,
Feb 17, 2023, 12:29:36 AM2/17/23
to BBEdit-Talk
On Feb 16, 2023, at 22:15, ChristianBoyce <mac...@christianboyce.com> wrote:
...
In my new situation, I want to replace spaces with %20 but only in PART of the selected text. I have text like this:

[Joe J. Smith]<j...@joesmith.com><subject=Sign me up!><body=I want to subscribe to the newsletter.>

...


Hey Christian,

You can't do this very easily with AppleScript, particularly because of the selected text requirement.

The only way I know of using AppleScript would be to loop the find using the selecting match option and to replace your spaces in the selected match.

You'd have to grab the first line and last line of the selection and test for those as you loop through. I've done this kind of thing now and then, and for a long document it's pretty slow.
a
You'd really expect to be able to find all instances and then loop through them directly, but unfortunately BBEdit doesn't support that.

Provided I didn't have to worry about "<subject=Sign me up!>" spanning lines I'd do this with a Perl filter.

The selection goes to Perl as STDIN.  You can then loop through line by line testing for your pattern and when found replace the spaces in only it, and once complete the selection will be replaced with STDOUT.

Something like this should suffice, and compared to AppleScript it will be lightning quick.

#!/usr/bin/env perl -sw
# ----------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2012/11/27 08:12
# dMod: 2023/02/16 23:18
# Task: Encode Spaces in Text Selection for a Given Pattern.
# Tags: @ccstone, @Shell, @Script, @Encode, @Spaces, @RegEx
# ----------------------------------------------------------
use v5.010;

while (<>) {
    if ( m!(.+)(<subject=.+?>)(.+)! ) {
        my $prefixStr  = $1;
        my $newSubject = $2;
        my $suffixStr  = $3;

        $newSubject =~ s!\h!\$20!g;
        say $prefixStr . $newSubject . $suffixStr;
    }
}

# ----------------------------------------------------------

--
Take Care,
Chris

Bruce Van Allen

unread,
Feb 17, 2023, 10:17:43 AM2/17/23
to bbe...@googlegroups.com
Chris, did you mean:

$newSubject =~ s!\h!\%20!g;

rather than

$newSubject =~ s!\h!\$20!g;


— Bruce

_bruce__van_allen__santa_cruz_ca_
> --
> This is the BBEdit Talk public discussion group. If you have a feature request or need technical support, please email "sup...@barebones.com" rather than posting here. Follow @bbedit on Twitter: <https://twitter.com/bbedit>
> ---
> You received this message because you are subscribed to the Google Groups "BBEdit Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to bbedit+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/bbedit/8ab01435-e68a-4025-ba87-062c99fe481bn%40googlegroups.com.

Christopher Stone

unread,
Feb 17, 2023, 1:35:58 PM2/17/23
to BBEdit-Talk
On Feb 16, 2023, at 23:48, Bruce Van Allen <b...@cruzio.com> wrote:
Chris, did you mean:
$newSubject =~ s!\h!\%20!g;
rather than
$newSubject =~ s!\h!\$20!g;


Hey Bruce,

Yes indeed.

Thanks for catching my mistake.  :-)

--
Take Care,
Chris

Bruce Van Allen

unread,
Feb 17, 2023, 1:38:54 PM2/17/23
to bbe...@googlegroups.com

> On Feb 17, 2023, at 10:35 AM, Christopher Stone <listmei...@gmail.com> wrote:
> Thanks for catching my mistake. :-)

Only happened because I always study your great scripts to learn from them!

— Bruce

_bruce__van_allen__santa_cruz_ca_

Christopher Stone

unread,
Feb 17, 2023, 1:48:57 PM2/17/23
to BBEdit-Talk
On Feb 17, 2023, at 12:38, Bruce Van Allen <b...@cruzio.com> wrote:
Only happened because I always study your great scripts to learn from them!


Whups I just realized I only tested with lines that would match the find criteria, so other lines would be excluded.

Here's the fix for that.

#!/usr/bin/env perl -sw
# ----------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2012/11/27 08:12
# dMod: 2023/02/17 12:43
# Task: Encode Spaces in Text Selection for a Given Pattern.
# Tags: @ccstone, @Shell, @Script, @Encode, @Spaces, @RegEx
# Vers: 2.00
# ----------------------------------------------------------
use v5.010;

while (<>) {
   if ( m!(.+)(<subject=.+?>)(.+)! ) {
      my $prefixStr  = $1;
      my $newSubject = $2;
      my $suffixStr  = $3;

      $newSubject =~ s!\h!%20!g;
      say $prefixStr . $newSubject . $suffixStr;

      

   } else {

      print;

      

   }
}

Reply all
Reply to author
Forward
0 new messages