Snippets from today’s coding (Using SED to Parse Alfred input)

RegEx made to look like FedExMore snippets from my adventures with @AlfredApp and AppleScript.  For this one, I needed to fulfill a couple of requirements, similar in nature to my previous e-mail code:

  1. Most importantly I needed to figure out a way to utilize a single string entry into Alfred that could be interpreted with multiple variables.  Example:  Triggering alfred and typing trigger Severity-Subject-Context producing three distinct variables within an AppleScript:
    1. Severity
    2. Subject
    3. Context
  2. I had to use AppleScript because passing the arguments was dependent upon the AppleScript library references, so just popping a shell script wasn’t fully the answer
  3. Finally, I needed to grab those values and then create three different e-mails directed to three different parties with (you should probably see where I’m going with this) three different contexts (this was the easiest part).

The hardest part about all of this is dealing with Alfred’s input scheme.  As far as I can tell (and even using @preppeller’s own Tumblr) it seems that there’s no easy way to differentiate a single Alfred string to multiple variables.  In that Tumblr piece, Preppeller shows off the following code snippet:

on alfred_script(q)
  tell application "Things"
    parse quicksilver input q
  end tell
end alfred_script

This would be great if it weren’t for the fact that instead of Alfred handling the variables of the input, he’s turning to @CulturedCode’s Things App and its ability to parse out syntax provided.  In my situation unfortunately, @SparrowApp doesn’t have that ability and it’s what I needed (I blame neither party!).  Another good example actually got to me from the team itself while writing this blog, take a look for how he handled it using a shell script.

So putting around, I decided I was going to use AppleScripts “do shell script” to parse out the line using sed and a relatively complex regex.  I’m sure I could do this much, much better some other way, but this is how I did it!  I figured that since it took me a bit of time, I could help others by providing my tools.  I’m not going to link anything for a bit, but please see links at the bottom of the post for some of the tools and resources I tapped into.  More after the break.I broke this down into a few parts:

  1. Defining the string to be used and it’s syntax.  Obviously my syntax is different in my own script, but the concept is the same:  Define a standard form you’re going to take every time you use this trigger.  My context was stated above: trigger Severity-Subject-Context
  2. Construct a regex based on Shell for us to parse variables from that single string in the appropriate context using RE grouping
  3. Put together and set a variable as a text-string combining a standard Shell command structure with Alfred’s input and grabbing selected groups from that regex (e.g. – echo “Severity-Subject-Context” | sed -E ’s:([A-Za-z0-9]+)-([A-Za-z0-9]+)-(.+$):\1:’ - will grab the first returned match of the string echo’d previously).  In the example above, the context result will be “Severity” if run from Terminal.
  4. Finally, after generating the string as text, set a new variable based on the “do shell script” mentioned above.

You can see the code example here:

on alfred_script(q)
	set q to q as text
	#Set the shell script command echos
	set severitySed to "echo \"" & q & "\" | sed -E 's:([A-Za-z0-9]+)-([A-Za-z0-9]+)-(.+$):\\1:'" as text
	set subjectSed to "echo \"" & q & "\" | sed -E 's:([A-Za-z0-9]+)-([A-Za-z0-9]+)-(.+$):\\2:'" as text
	set contextSed to "echo \"" & q & "\" | sed -E 's:([A-Za-z0-9]+)-([A-Za-z0-9]+)-(.+$):\\3:'" as text

	#Run shell scripts to set the email variables
	set severityLevel to do shell script severitySed
	set subjectName to do shell script subjectSed
	set contextDesc to do shell script contextSed

end alfred_script

I want to make sure there are a couple of things to note that are slightly different about the Terminal command and how this had to get put together because it tripped me up:

  •  The first variables set (xyzSed) need to be put together very carefully.  There are a lot of escapes and for simplicity’s sake, I changed out the traditional “sed -E ‘s/” context to be a colon.  This is perfectly fine, just remember that from here out your Sed command will use the : marker as your separator value.  So if a traditional format would be “sed ‘s/First/Last/’” it is now going to be “sed ‘s:first:last:’“.  In my opinion this is hundreds of times easier to read and I’m still not entirely sure why more people don’t teach it this way.  As I was learning how to use the command more effectively it finally just came to me copying and pasting example strings into textedit and running a find/replace on any forward slash.
  • As a follow-up to that note, you’ll notice that instead of quotes on the sed command I used apostrophes and that’s totally cool
  • The last note about escaping was the request to grab Group 1-3 of the data.  In sed, providing “\1” as the replacement string will tell sed to go back and find the first group of data and simply supply only that data back as a result.  However it tripped me up a bit that I had to double backslash in order to escape it and pass it literally.
  • Finally, you’ll notice that I threw everything into pre-constructed variables and THEN ran the “do shell script” on them.  I honestly do not know why – it could be ineptitude or AppleScript being wonky, but unless I threw them to their own variable to generate the line pre-script time, AS would refuse to handle the more complex “do shell script echo XYZ | sed blah blah”  This was my workaround.

Finally after all of that, the only hard part was going back and snatching the context for my e-mails, their recipient fields, and generating from there.  The sky is the limit once you’ve got that regex and sed down, so go to town!

Hope this helps any of you out there, cheers!

-C


Resources

Stanford’s Online Regex Analyzer – Helps defining the regex and in particular getting the groups parsed properly for variable assignment.

@grymoire (Bruce Barnett)’s wonderful SED examples page - This guy’s page almost single-handedly taught me sed

Regular-Expressions.info – This seems obvious, but when you’re like me and starting from scratch, these guys help.

 

  • http://twitter.com/lovekindstrand Love Kindstrand

    Thanks a lot for this, exactly what I was looking for!

  • http://twitter.com/jdfwarrior David Ferguson

    This could be done easier with the cut command, that way you don’t have to worry about regular expressions.

    echo this-is a-test | cut -d “-” -f 1
    echo this-is a-test | cut -d “-” -f 2
    echo this-is a-test | cut -d “-” -f 3

    That gives you all three pieces that were separated by a -