Jump to content

Find & Replace with RegEx and JavaScript


Recommended Posts

Posted (edited)

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
Posted
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.

 

 

Posted (edited)

"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
Posted
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.

Posted (edited)

They are the same as the notes. 
 

Replace He with She

Replace Mr with Ms 

 

I am using basic string replace. 

Edited by slyfox
Posted (edited)
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
Posted

@deanishe

 

Thank you for the script. It works. 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?

 

 

Screen Shot 2019-09-14 at 9.50.28 AM.png

Posted
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.

  • 3 months later...
Posted

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]);
}

 

Posted
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);
}

 

Posted
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. :( 

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
Posted
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?

Posted

@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

Posted
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]);
}

 

Posted

@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]);
}

 

Posted
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.

Posted
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 

Posted

@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]);
}

 

Posted (edited)

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
Posted
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
}

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...