RegEx - Find and Replace with Variables

I am trying to figure out how to use Find & Replace with RegEx to manipulate text. In this case, want to set a variable using RegEx and then replace text with the variable.

Text:

Mr. John Smith

Mr. XX goes to town.

Script

// define regex to use...
const findRegex = /([M][r-s]\.\s)(\w*\s)(\w*)/g;
// define replacement expression...
const FirstName = "$2";
const LastName = "$3";

//Find Text
const XX = "XX";
//

// do the replacement...
draft.content = draft.content.replace(XX, LastName);
draft.update();

Result:

Mr. John Smith

Mr. $3 goes to town.

What am I doing wrong?

Is this different to what you asked here, where I highlighted the missing usage?

A Find/Replace "Step" for Custom Actions (with RegEx)?

Same. I just started a new threat for better clarity.

you set-up a regex string and never use it

Hmm. Can you please show what the code would look like? I am trying to replace all instances of XX with the group “$3” from RegEx.

You’re defining a regex like this.

const findRegex = /([M][r-s]\.\s)(\w*\s)(\w*)/g;

But you don’t use it anywhere.

You define a constant xx which isn’t a regex expression.

const XX = "XX";

You’re using that in your replace instruction.

Replacing “all instances of ‘XX’ with the group ‘$3’ from the regex” doesn’t really make any sense to me from a regex point of view.

From your initial text and result, it looks like you want to replace an instance of the text “XX” with the text “$3”. No regex group.

If you want to replace all instances, then a line like this would suffice.

draft.content = draft.content.replace(/XX/g, "$3");

But I’m not wholly convinced that is what you are really asking here looking at the sorts of terms being used. Based on that I’m going to go a bit further and question what it is you actually want to do…

If you want to find an instance of a salutation forename and surname and then pick out the surname as the third group, something like your const findRegex would find a match when you run it; but as it stands that’s defined for global, so how would you know which instance of the name pattern to use?

I think what you are probably looking to do is find the first instance of a salutation, forename, surname, get the surname from that, and then do a find and replace across all instances of the text “XX” in your draft, replacing that with the surname.

Could you clarify what it is is you are trying to do?

In case it’s useful, here’s a quick jsfiddle on picking out (matching) the surname that you can experiment with if you are looking to do something like the latter above.

https://jsfiddle.net/sylumer/L3gnxzt6/

I am trying to figure out how to convert a simple Keyboard Maestro (KM) text manipulation workflow into Drafts action. Please note that I don’t know Java Script but perhaps with some examples, I can figure out the basics principles of RegEx Find & Replace in Javascript.

A plain text document contains an instance of “Mr. John Smith” (name varies) The rest of the document refers to the client as Mr. XX. My KM workflow copies text to clipboard and then runs the RegEx with variables.

/([M][r-s]\.\s)(\w*\s)(\w*)/g;

Where:

Group 1 = Mr.
Group 2 = John
Group 3 = Smith

Group 2 is set to variable FirstName
Group 3 is set to variable LastName

I then tell KM to replace all instances of XX with LastName variable.

Okay, so it looks like my guess was right. That example I gave above shows you how to get the surname.

Take the surname and use this with the XX in a simple replace.

The only regex is to get the surname and the jsfiddle gives you got the basis of the code to do that. The standard replace is in effect the same approach for the replace that you began with.

Is that now enough for you to modify your script?

Sorry @sylumer, I’m not quite there.

Mr. John Smith

Mr. XX goes to town.

// define regex to use...
const findRegex = "/([M][r-s]\.\s)(\w*\s)(\w*)/g";
// define replacement expression...

// do the replacement...
draft.content = draft.content.replace(/XX/g, "$3");
//Update the draft
draft.update();

Produces

Mr. John Smith

Mr. $3 goes to town.

Ok then, see if you can follow what has been done here. This I believe applies the desired update as per your example.

draft.content = draft.content.replace(/XX/g,draft.content.match(/([M][r-s]\.\s)(\w*\s)(\w*)/)[3]);
draft.update();

Note that in your code above, you have still not applied the match operation that I demonstrated in the jsfiddle, and you are still passing a literal string in for the replace.

This works! Thank you.

I am trying to understand how this works.

  1. Replace the content of the text

draft.content.replace

  1. Find XX global - the entire content

/XX/g

  1. Replace with

,

  1. Draft content matches

draft.content.match(/([M][r-s]\.\s)(\w*\s)(\w*)/)[3]

I am confused about (/Regular Expression.) and [group three]

What does it mean when you put “()” next to “[]” ?

Well, this was broken down in the jsfiddle that I created for you, but to break it down further, try this:

  • draft.content is the content of your draft.
  • draft.content.match() is a function to look for a match in your draft content.
  • draft.content.match(/([M][r-s]\.\s)(\w*\s)(\w*)/) is a function to look for a match in your draft content matching the regular expression you provided at the beginning, but without the ‘g’ modifier for the reason I gave earlier.
    • I’m assuming at this point I don’t need to explain how the regular expression is defined as you are already using it and some things you wrote earlier suggest you might have an idea about that.
  • In JavaScript the square brackets indicate an array index.
    • If you don’t know what an array is, think of it as an ordered list.
  • draft.content.match(/([M][r-s]\.\s)(\w*\s)(\w*)/)[3] is a function to look for a match in your draft content matching the regular expression provided, and return the third element of the match.
    • The first element is the title.
    • The second element is the forename.
    • The third element is the surname, hence we want the third matched element.
    • JavaScript arrays are zero indexed, but the 0 index is populated with the entire match, the elements relate to the groups.

This makes sense. Thank you very much.

If I want to learn more about the basics of JavaScript to get better at using the Drafts app rather than programming (e.g., websites, code), what would your recommend as the next step?

I would recommend you don’t quite take that approach and that you do try and pick up some programming. Understanding how to use the tools when you are trying to use the tools will make a big difference. Often authors introduce the concepts through the use of a language, so if you are following some sort of well structured course, I suspect you would find them inextricably combined.

While the JavaScript learning content out there seems to be universally aimed at using it for the web, the core language remains the same. If you keep in mind anything that queries or updates the browser or the web page won’t work in Drafts, and that you would just be working with the Drafts app instead, that will get you a long way.

Apart from that Eloquent JavaScript is a good, freely available book, but using your favourite search engine and looking for ‘JavaScript Introduction’ would give you a wealth of options.

Once you have a grounding in a few of the basics of JavaScript, take a look at the Drafts scripting documentation, the examples spread throughout this forum, and of course the existing Drafts actions in the action directory that utilise script steps.