Jump to content
slyfox

Find & Replace with RegEx and JavaScript

Recommended Posts

I need a simple workflow to copy text -> use RegEx to replace various text within the clipboard content and paste it back.

 

My current workflow is to simply create a bunch of linked find and replace utility arguments inside Alfred. I am not sure if this is the best approach compared to a simple Javascript that includes a list of variables to replace. 

 

I don't know Java or any other programming language but sample Javascript looks simple enough to modify if someone can provide it.

Screen Shot 2019-09-12 at 8.11.09 PM.png

Screen Shot 2019-09-12 at 8.13.44 PM.png

Edited by slyfox

Share this post


Link to post
12 hours ago, slyfox said:

I am not sure if this is the best approach compared to a simple Javascript that includes a list of variables to replace.

 

A script would certainly be easier to add new items to.

 

12 hours ago, slyfox said:

simple enough to modify if someone can provide it

 

If you post some sample input and the expected output, sure.

 

 

Share this post


Link to post

"If you post some sample input and the expected output, sure."

 

@deanishe Are the examples (i.e., Mr. to Ms.) in the screenshots not clear?

 

 

Edited by slyfox

Share this post


Link to post
2 hours ago, slyfox said:

@deanishe Are the examples (i.e., Mr. to Ms.) in the screenshots not clear?

 

There are no examples in the screenshots. Those are the notes you've added. I can't see the actual contents of the Replace elements.

Share this post


Link to post

They are the same as the notes. 
 

Replace He with She

Replace Mr with Ms 

 

I am using basic string replace. 

Edited by slyfox

Share this post


Link to post
On 9/13/2019 at 6:06 PM, slyfox said:

There is a space after “He “ and “She “

 

😐 That isn't what you or your screenshots said earlier, is it? 

 

Here is a JavaScript that will replace some of your words. It's pretty clear where new entries go. Use it instead of all your Replace utilities. Put it in a Run Script action with Language = /usr/bin/osascript (JS) and with input as argv.

#!/usr/bin/osascript -l JavaScript

var replacements = [
	// (\W|^) matches non-word character or start
	// (\W|$) matches non-word character or end
	// $1 and $2 are the first and second match groups,
	// where a match group is whatever matches the contents
	// of a pair of parentheses.
	[/(\W|^)He(\W|$)/gm, '$1She$2'],
	[/(\W|^)he(\W|$)/gm, '$1she$2'],
	[/(\W|^)Mr(\W|$)/gm, '$1Ms$2'],
	[/(\W|^)His(\W|$)/gm, '$1Her$2'],
	[/(\W|^)his(\W|$)/gm, '$1her$2'],
];

function feminise(s) {
	replacements.forEach(function(l) {
		s = s.replace(l[0], l[1]);
	});
	return s;
}

function run(argv) {
	return feminise(argv[0]);
}

 

Edited by deanishe
AS -> JS

Share this post


Link to post
2 hours ago, slyfox said:

Any idea why when the new content is pasted, there is a new line at the bottom whereas the original content does not have a new line?

 

Because osascript adds a newline. Run the output through a Transform utility to remove the extra whitespace.

Share this post


Link to post

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.

 

6d19e25af33123c032b3caedb0dd593400d9f679

 

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.

 

Based on the solution in this forum post for Find & Replace as well as as this forum post - https://forums.getdrafts.com/t/regex-find-and-replace-with-variables/6294/11?u=slyfox

 

I tried to figure this out myself but it does not seem to be working.

 

Can you please advise how to make this work?

#!/usr/bin/osascript -l JavaScript
var replacements = [
    // (\W|^) matches non-word character or start
    // (\W|$) matches non-word character or end
    // $1 and $2 are the first and second match groups,
    // where a match group is whatever matches the contents
    // of a pair of parentheses.
    [/(\W|^)XX(\W|$)/gm, '$1/([M][r-s]\.\s)(\w*\s)(\w*)/)[3]$2'],
];
function feminise(s) {
    replacements.forEach(function(l) {
        s = s.replace(l[0], l[1]);
    });
    return s;
}
function run(argv) {
    return cleanReport(argv[0]);
}

 

Share this post


Link to post
1 hour ago, slyfox said:

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.

 

6d19e25af33123c032b3caedb0dd593400d9f679

 

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.

 

Based on the solution in this forum post for Find & Replace as well as as this forum post - https://forums.getdrafts.com/t/regex-find-and-replace-with-variables/6294/11?u=slyfox

 

I tried to figure this out myself but it does not seem to be working.

 

Can you please advise how to make this work?


#!/usr/bin/osascript -l JavaScript
var replacements = [
    // (\W|^) matches non-word character or start
    // (\W|$) matches non-word character or end
    // $1 and $2 are the first and second match groups,
    // where a match group is whatever matches the contents
    // of a pair of parentheses.
    [/(\W|^)XX(\W|$)/gm, '$1/([M][r-s]\.\s)(\w*\s)(\w*)/)[3]$2'],
];
function feminise(s) {
    replacements.forEach(function(l) {
        s = s.replace(l[0], l[1]);
    });
    return s;
}
function run(argv) {
    return cleanReport(argv[0]);
}

 

 

Not super familiar with JS. Does this work?

 

var replacements = [
    // (\W|^) matches non-word character or start
    // (\W|$) matches non-word character or end
    // $1 and $2 are the first and second match groups,
    // where a match group is whatever matches the contents
    // of a pair of parentheses.
    /(\W|^)XX(\W|$)/gm,
];

function getName(s) {
	let lastname = /(?:[M][r-s]\.\s)(?:\w+)(\s\w*)/;
    return s.match(lastname)[1]
}
function cleanReport(s) {
    replacements.forEach(function(l) {
        s = s.replace(l, getName(s));
    });
    return s;
}
function run(sb) {
    return cleanReport(sb);
}

 

Share this post


Link to post
8 hours ago, Terminal said:

 

Not super familiar with JS. Does this work?

 


var replacements = [
    // (\W|^) matches non-word character or start
    // (\W|$) matches non-word character or end
    // $1 and $2 are the first and second match groups,
    // where a match group is whatever matches the contents
    // of a pair of parentheses.
    /(\W|^)XX(\W|$)/gm,
];

function getName(s) {
	let lastname = /(?:[M][r-s]\.\s)(?:\w+)(\s\w*)/;
    return s.match(lastname)[1]
}
function cleanReport(s) {
    replacements.forEach(function(l) {
        s = s.replace(l, getName(s));
    });
    return s;
}
function run(sb) {
    return cleanReport(sb);
}

 

 

It does not. :( 

Share this post


Link to post
Posted (edited)

Can you post a same paragraph for me to test on. 

 

 

this appears to work for me.

 

#!/usr/bin/osascript -l JavaScript

var replacements = [
	// (\W|^) matches non-word character or start
	// (\W|$) matches non-word character or end
	// $1 and $2 are the first and second match groups,
	// where a match group is whatever matches the contents
	// of a pair of parentheses.
	[/(\W|^)He(\W|$)/gm, '$1She$2'],
	[/(\W|^)he(\W|$)/gm, '$1she$2'],
	[/(\W|^)Mr(\W|$)/gm, '$1Ms$2'],
	[/(\W|^)His(\W|$)/gm, '$1Her$2'],
	[/(\W|^)his(\W|$)/gm, '$1her$2'],
	[/(\W|^)Him(\W|$)/gm, '$1Her$2'],
	[/(\W|^)him(\W|$)/gm, '$1her$2'],
];

var nameReplacement = /(\W|^)XX(\W|$)/gm;

function getName(s) {
	let lastname = /(?:[M][r-s]\.\s)(?:\w+)(\s\w*)/;
    return s.match(lastname)[1]
}

function feminise(s) {
	replacements.forEach(function(l) {
		s = s.replace(l[0], l[1]);
	});
	s = s.replace(nameReplacement, getName(s));
	return s;
}

function run(argv) {
	return feminise(argv[0]);
}

 

Edited by Terminal

Share this post


Link to post
9 hours ago, slyfox said:

It does not. :( 

 

This is not a useful answer. @Terminal is very kindly spending their time helping you, but you are not being helpful in return.

 

When something doesn't work, explain exactly why it doesn't work. What was the input, what was the output, and what was the expected output?

Share this post


Link to post

@Terminal Almost there.

 

@deanishe Sorry, I'll be more specific.

 

input:

Mr. John Smith
Mr. XX goes to town.

Output:

Mr. John Smith

Mr. Smithgoes to town.

 

Javascript used

 

#!/usr/bin/osascript -l JavaScript

var replacements = [

];

var nameReplacement = /(\W|^)XX(\W|$)/gm;

function getName(s) {
	let lastname = /(?:[M][r-s]\.\s)(?:\w+)(\s\w*)/;
    return s.match(lastname)[1]
}

function cleanup(s) {
	replacements.forEach(function(l) {
		s = s.replace(l[0], l[1]);
	});
	s = s.replace(nameReplacement, getName(s));
	return s;
}

function run(argv) {
	return cleanup(argv[0]);
}

 

Can I also ask (trying to understand)

 

1. Why do we need line 2-5? Can't we just start with line

var nameReplacement = /(\W|^)XX(\W|$)/gm;

 

2. return s.match(lastname)[1] --> Why is there a number 1 rather then number 3? I thought that the last name will be group $3 in RegEx

Share this post


Link to post
51 minutes ago, slyfox said:

@Terminal Almost there.

 

@deanishe Sorry, I'll be more specific.

 

input:


Mr. John Smith
Mr. XX goes to town.

Output:


Mr. John Smith

Mr. Smithgoes to town.

 

Can I also ask (trying to understand)

 

1. Why do we need line 2-5? Can't we just start with line


var nameReplacement = /(\W|^)XX(\W|$)/gm;

 

2. return s.match(lastname)[1] --> Why is there a number 1 rather then number 3? I thought that the last name will be group $3 in RegEx

 

 

This should fix it. And to answer your questions

 

 

1.  I left replacement because I wasn't full sure of your use case. I remove the unneeded code.

2. return s.match(lastname)[1] works because of the regex we are using /(?:[M][r-s]\.\s)(?:\w+\s)(\w*)/ The ?: in the capture groups "()" tells the regex parser to ignore the grouping. Basically, look for this pattern as a group, but ignore it when returning matches. so we use [1] because [0] contains the full match and [1] contains the match we asked for.

 

 

 

#!/usr/bin/osascript -l JavaScript

var nameReplacement = /(\W|^)XX(\W|$)/gm;

function getName(s) {
	let lastname = /(?:[M][r-s]\.\s)(?:\w+\s)(\w*)/;
    return s.match(lastname)[1]
}

function cleanup(s) {
	s = s.replace(nameReplacement, "$1"+getName(s)+"$2");
	return s;
}

function run(argv) {
	return cleanup(argv[0]);
}

 

Share this post


Link to post

@Terminal

 

Through some trial and error I am trying to add another RegEx find & Replace but so far nothing happens. This time I am trying to replace "DOB" with "Date of Birth: January 10, 2020" 

 

All instances of "DOB" should turn into "January 10, 2020"

 

Also, how would you combine multiple find and replace scripts into one? 

 

#!/usr/bin/osascript -l JavaScript

var dobReplacement = /(\W|^)DOB(\W|$)/gm;

function getDateofBirth(s) {
	let dob = /(?:Date\sof\sBirth:\s)?:(\w+\s\d{1,2}\,\s\d{4})/;
    return s.match(dob)[1]
}

function replaceDOB(s) {
	s = s.replace(dobReplacement, "$1"+getDateofBirth+"$2");
	return s;
}

function run(argv) {
	return cleanup(argv[0]);
}

 

Share this post


Link to post
4 minutes ago, slyfox said:

s = s.replace(dobReplacement, "$1"+getDateofBirth+"$2");

 

You're trying to replace text with a function. Not the result of calling a function. A literal function.

Share this post


Link to post
3 minutes ago, slyfox said:

@Terminal

 

Through some trial and error I am trying to add another RegEx find & Replace but so far nothing happens. This time I am trying to replace "DOB" with "Date of Birth: January 10, 2020" 

 

All instances of "DOB" should turn into "January 10, 2020"

 

Also, how would you combine multiple find and replace scripts into one? 

 


#!/usr/bin/osascript -l JavaScript

var dobReplacement = /(\W|^)DOB(\W|$)/gm;

function getDateofBirth(s) {
	let dob = /(?:Date\sof\sBirth:\s)?:(\w+\s\d{1,2}\,\s\d{4})/;
    return s.match(dob)[1]
}

function replaceDOB(s) {
	s = s.replace(dobReplacement, "$1"+getDateofBirth+"$2");
	return s;
}

function run(argv) {
	return cleanup(argv[0]);
}

 


mill take a look when I get home. I’ll also write it to be a little bit more flexible. 
 

Again, JavaScript is not a strength of mine, I use python and golang much more. I’ll do what I can 

Share this post


Link to post

@slyfox Here is working replacement of DOB

 

To better help you, what all should this script do? Should one workflow, change pronouns, dob, and name? Or do you want to trigger all of these individually? Can you explain your ideal workflow? As it is completely possible, but without understanding what you are fully trying to accomplish, it is harder to create what you need.

 

 

#!/usr/bin/osascript -l JavaScript

var dobReplacement = /(\W|^)DOB(\W|$)/gm;

function getDateofBirth(s) {
	let dob = /(?:Date\sof\sBirth:\s)(\w+\s\d{1,2}\,\s\d{4})/;
    return s.match(dob)[1]
}

function replaceDOB(s) {
	s = s.replace(dobReplacement, "$1"+getDateofBirth(s)+"$2");
	return s;
}

function run(argv) {
	return replaceDOB(argv[0]);
}

 

Share this post


Link to post

I am trying to replace a Keyboard Maestro workflow with Alfred workflow. 

 

1. CMD+A to select text
2. Copy to Clipboard
3. Execute Find & replace
4. Paste back the results.

 

For step 3 my report will have this info at the top:

### Client Info

- Clinic: Advanced Healthcare
- Name: Mr. John Smith
- Date of Birth: January 10, 1980
- Date of Loss: January 10, 2019
- Date of Assessment: January 10, 2020

 

I need to find and set variables:

 

firstName = John

lastName = Smith

dob = January 10, 1980

dol = January 10, 2019

 

Then replace (content of the report):

 

NN with firstName --> ([M][r-s]\.\s)(\w*\s)(\w*) - group 2

XX with lastName --> ([M][r-s]\.\s)(\w*\s)(\w*) - group 3

DOB with dob --> Date\s\of\s\Birth:\s(\w+\s\d{1,2}\,\s\d{4})

DOL with dol --> Date\s\of\s\Loss:\s(\w+ \d{1,2},\s\d{4})

 

 

Screen Shot 2020-01-10 at 9.32.09 PM.png

Screen Shot 2020-01-10 at 9.22.10 PM.png

Edited by slyfox

Share this post


Link to post
2 hours ago, slyfox said:

I am trying to replace a Keyboard Maestro workflow with Alfred workflow. 

 

1. CMD+A to select text
2. Copy to Clipboard
3. Execute Find & replace
4. Paste back the results.

 

For step 3 my report will have this info at the top:


### Client Info

- Clinic: Advanced Healthcare
- Name: Mr. John Smith
- Date of Birth: January 10, 1980
- Date of Loss: January 10, 2019
- Date of Assessment: January 10, 2020

 

I need to find and set variables:

 

firstName = John

lastName = Smith

dob = January 10, 1980

dol = January 10, 2019

 

Then replace (content of the report):

 

NN with firstName --> ([M][r-s]\.\s)(\w*\s)(\w*) - group 2

XX with lastName --> ([M][r-s]\.\s)(\w*\s)(\w*) - group 3

DOB with dob --> Date\s\of\s\Birth:\s(\w+\s\d{1,2}\,\s\d{4})

DOL with dol --> Date\s\of\s\Loss:\s(\w+ \d{1,2},\s\d{4})

 

 

Screen Shot 2020-01-10 at 9.32.09 PM.png

Screen Shot 2020-01-10 at 9.22.10 PM.png

 

 

This definitely can be cleaned up better. But test this out.

 

A video in action https://gifyu.com/image/mVZs

 

#!/usr/bin/osascript -l JavaScript

var firstNameReplacement = /(\W|^)NN(\W|$)/gm;
var lastNameReplacement = /(\W|^)XX(\W|$)/gm;
var dobReplacement = /(\W|^)DOB(\W|$)/gm;
var dolReplacement = /(\W|^)DOL(\W|$)/gm;

function getName(s) {
	let pattern = /Name:\s(?:[M][r-s]\.\s)(\w*)\s(\w*)/;
    return s.match(pattern)
}

function replaceName(s) {
	s = s.replace(firstNameReplacement, "$1"+getName(s)[1]+"$2");
	s = s.replace(lastNameReplacement, "$1"+getName(s)[2]+"$2");
	return s;
}

function getDateofBirth(s) {
	let dob = /(?:Date\sof\sBirth:\s)(\w+\s\d{1,2}\,\s\d{4})/;
    return s.match(dob)[1]
}

function replaceDOB(s) {
	s = s.replace(dobReplacement, "$1"+getDateofBirth(s)+"$2");
	return s;
}

function getDateofLoss(s) {
	let dol = /(?:Date\sof\sLoss:\s)(\w+\s\d{1,2}\,\s\d{4})/;
    return s.match(dol)[1]
}

function replaceDOL(s) {
	s = s.replace(dolReplacement, "$1"+getDateofLoss(s)+"$2");
	return s;
}


function run(argv) {
	var content = argv[0];
	content = replaceName(content);
	content = replaceDOB(content);
	content = replaceDOL(content);
	return content
}

 

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...