How to find all e-mail addresses in string/variable via regex?

Hi Keyboard-Maestros,

I am currently trying to extract all e-mail addresses from a string / variable, but cannot figure out how to save more than one. The regex below does find the first e-mail address in the string, but then stops. I tried some variations with repeat-actions but cannot get to other capture groups..

Do you have an idea on how to solve this?

Any help on this would be very appreciated.

Thanks a lot and have a great 2018!

This is a much discussed issue on which views range from the sceptical:

https://davidcel.is/posts/stop-validating-email-addresses-with-regex/

to the hopeful:

http://emailregex.com/

More generally, if you do think that a regex will work in your context, you need a For Each to work through regex-matching substrings:

You're on the right track. Try this, using the KM For Each action (KM Wiki). Below is an example of how this can be done in general. You will need to replace data in these Actions with YOUR data:

  1. Set Local__SourceStr
  2. The RegEx in the subscrings block of the For Each

Example Results

##Macro Library   @RegEx Extract Multiple Matches into Results List @Example


####DOWNLOAD:
<a class="attachment" href="/uploads/default/original/3X/3/7/378a48a9a8a2bc56e19a0b934e41ff532949f971.kmmacros">@RegEx Extract Multiple Matches into Results List @Example.kmmacros</a> (4.3 KB)
**Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.**

---



<img src="/uploads/default/original/3X/8/c/8ca6c972aecc6ebc8651710f8cf63561973bd19c.png" width="469" height="1223">

Questions?

Hey Marc,

I repurposed my Perl script from the β€œFind Email Address?” topic to operate on text in any given Keyboard Maestro variable.

The email address RegEx pattern is by Jan Goyvaerts who's been a big name in the RegEx community for many years.

To use the script all you have to do is change the value of the $kmVarName variable in the script to exactly match the name of the Keyboard Maestro variable you want to search.

Currently the output is to a Keyboard Maestro window, but you can change that as needed.

-Chris


Extract Email Addresses from Source Text.kmmacros (7.3 KB)

And, of course, as alternatives to Perl, we could generalize the same kind of thing in AppleScript:

-- uniqueSortedMatchesInText :: Regex -> String -> [String]
on uniqueSortedMatchesInText(rgx, s)
    sort(nub(map(my headDef, regexMatches(rgx, s))))
end uniqueSortedMatchesInText

or in JavaScript for Automation:

// uniqueSortedMatchesInText :: Regex -> String -> [String]
const uniqueSortedMatchesInText = (rgx, s) =>
    sort(nub(map(headDef, regexMatches(rgx, s))));

All emails in selected text.kmmacros (27.5 KB)

1 Like

The AppleScript works perfectly for me and does the trick for what I was trying to achieve. Thank you so much, this will save me hours over hours :slight_smile:

1 Like

So glad I found this one. It’ll be a huge time saver!

1 Like

I have tried changing variables in your script so it wil extract email and then remove mailto links ones could you let me know what I would have to do to get this variable to work

"textFromInput.match(/([a-zA-Z0-9.-]+@[a-zA-Z0-9.-]+.[a-zA-Z0-9._-]{3}(?!mailto))/gi) "

<!doctype html>

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">

<title>Email Extractor</title>

Email Extractor


Input Text
Use "double"
Use 'single'
No quotes
Extract

Extracted

Copy
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://raw.githubusercontent.com/lgarron/clipboard-polyfill/master/build/clipboard-polyfill.js"></script>
<script>
    
    function extractEmails ( textFromInput ){
    let emails = textFromInput.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]{3}(?!mailto))/gi);
        return _.uniq(emails);
    
}
    function makeList () {
  var textFromInput = $('textarea#text').val();
   var emails = extractEmails(textFromInput);
	var list = '';
var quotes = ""
if ($('input[name=quotes]:checked', '#emailExtractor').val() === 'option1') {quotes = "\"";}
if ($('input[name=quotes]:checked', '#emailExtractor').val() === 'option2') { quotes = "'";}
$.each(emails, function(index, email){
     list = list + `${quotes}${email}${quotes}, `;
  });
$("#emails").empty().text(list.substring(0,list.length-2));
$('textarea#text').val('');

}