Correct SED Usage

I’m trying to use Kim Hunter’s SED Regular Expression Action in my Automator workflow. Unfortunately, I’m not familiar with the syntax of SED commands and I can’t understand the documentation that I’ve found.

I’m trying to find all the instances of string between two other specified strings in a text file. For example…

Text file:
sasquatch human centipede balderdash godzilla

string 1: human
string 2: godzilla

I want it to return string 3: centipede balderdash

I thought the syntax was: sed -n ‘/human/,/godzilla/p’ filename, but this is giving me the error ‘unterminated substitute in regular expression’ in automator. When I try this command directly in the terminal, it just prints back the entire unmodified textfile.

Any help would be greatly appreciated. Thank you.

Hi,

I’m not great with sed, but this works when I tested it:

 sed  -e 's/.*human//'  -e 's/godzilla.*//'

You might also find this link useful: http://www.grymoire.com/Unix/Sed.html

Best wishes

John M

[edited to add link]

Hello.

I have a great link to some 1 liners with sed that one can learn a little from the file is stuffed with “handy” 1 liners which might give you a starting point sed1line.txt.

There is also a tutorial on sed which can be found here:Sed an Introduction and tutorial which also is mentioned in the post above. That tutorial is particularly useful for understanding the construct used in the post above.

If you google the exact phrase : “SED – A Non-interactive Text Editor” (without hyphens) then the original manual for Sed in Pdf format should turn up in the first position.

Best Regards

McUsr

sed -e 's/.*images//' -e 's/maps.*//' /Users/computername/Desktop/temp2.txt

works perfectly in terminal - Thanks John!

However, in automator I get the error message: “Bad flag in substitute command: ‘s’” with and without using the filepath. Does anyone know what this is referring to?

McUsr and John - Thanks for the resources, I will read through them.

Wild guess is that you must escape something - maybe the apostrophe.

I really don’t know what I’m talking about, just a guess, as I don’t have that Automator action.

You can start testing if the first expression works out all right. That is without the -e switch and what follows. Maybe the action is implemented in such a way that it doesn’t support the -e switch.

You better look at the examples of usage. Look particularly for any -e expressions.
Look for the format of his expressions in the examples.

Good Luck

McUsr

You can’t use flags in the box.

McUsr is correct.

Here is the code that calls the sed command the only reason i built this was to use \t in the expression for TAB

sed $isExt “echo $regExp | sed 's/\\t/ /g'”;

To use it the way you intend i would open SED Regular Expression.action/Contents/Resources/main.command might work

sed $isExt echo $regExp | sed 's/\\t/ /g';

I should upgrade the action so that it takes other flags

Hello.

I have a work around for you using an applescript with an automator action.

The script comes from this Script Tutorial by Adam Bell on the usages of AppleScript’s text item delimiters


set t to "My father has spanked me, and my mother has spanked me; all my aunts and uncles have spanked me for my 'satiable curtiosity; and still I want to know what the Crocodile has for dinner!"

extractBetween(t, "my ", ";") --> "'satiable curtiosity"
---- The handler ----
to extractBetween(SearchText, startText, endText)
	set tid to AppleScript's text item delimiters -- save them for later.
	set AppleScript's text item delimiters to startText -- find the first one.
	set endItems to text of text item -1 of SearchText -- everything after the first.
	set AppleScript's text item delimiters to endText -- find the end one.
	set beginningToEnd to text of text item 1 of endItems -- get the first part.
	set AppleScript's text item delimiters to tid -- back to original values.
	return beginningToEnd -- pass back the piece.
end extractBetween

I thought I’d post this, because this does exactly the same.

Hopes this helps

Best Regards

McUsr

Kim - Thanks for responding but I’m not sure I understand your suggestion.

McUser - Great! I read the rest of that post also and it works as intended by itself.

I’m run into a new issue when I try to integrate this code into the Automator.

Here’s how I have it setup in Automator:

Get Specified Text:
My father has spanked me, and my mother has spanked me; all my aunts and uncles have spanked me for my 'satiable curtiosity; and still I want to know what the Crocodile has for dinner!

Run AppleScript:

on run {input, parameters}
	extractBetween(input, "my", ";") --> "'satiable curtiosity"
end run

---- The handler ----
to extractBetween(SearchText, startText, endText)
	set tid to AppleScript's text item delimiters -- save them for later.
	set AppleScript's text item delimiters to startText -- find the first one.
	set endItems to text of text item -1 of SearchText -- everything after the first.
	set AppleScript's text item delimiters to endText -- find the end one.
	set beginningToEnd to text of text item 1 of endItems -- get the first part.
	set AppleScript's text item delimiters to tid -- back to original values.
	return beginningToEnd -- pass back the piece.
end extractBetween

Unfortunately, the result is “My father has spanked me, and my mother has spanked me”
and it should be the same as before “'satiable curtiosity”

Does anyone know what’s going on here?

Hello.

This is my very fist attempt of making an automator action ever, so be kind.
I have coerced the input from automator to text
And the I received the result of the handler to theText variable.
I was than able to see that it returned the correct text. But there is some missing pieces after
the applescript action I leave up to you or someone else. As said: Automator is not among my strongest sides.

on run {input, parameters}
	set myText to input as text
	set theText to extractBetween(myText, "my", ";")
	display dialog theText ” >  "'satiable curtiosity"
end run

---- The handler ----
to extractBetween(SearchText, startText, endText)
	set tid to AppleScript's text item delimiters -- save them for later.
	set AppleScript's text item delimiters to startText -- find the first one.
	set endItems to text of text item -1 of SearchText -- everything after the first.
	set AppleScript's text item delimiters to endText -- find the end one.
	set beginningToEnd to text of text item 1 of endItems -- get the first part.
	set AppleScript's text item delimiters to tid -- back to original values.
	return beginningToEnd -- pass back the piece.
end extractBetween

This returns the wanted text, you know better than me what to do from here. :wink:

Best Regards

McUsr

I apologize but if I read well, the original question was :

The given responces return the late extract matching the rule, not all of them.

Here is an attempt to really respond to it.


set t to "My father has spanked me, and my mother has spanked me; all my aunts and uncles have spanked me for my 'satiable curtiosity; and still I want to know what the Crocodile has for dinner!"

extractBetween(t, "my ", ";") --> "'satiable curtiosity"

---- The handler ----
to extractBetween(SearchText, startText, endText)
	set tid to AppleScript's text item delimiters -- save them for later.
	set AppleScript's text item delimiters to startText -- find the first one.
	set liste to text items 2 thru -1 of SearchText
	set AppleScript's text item delimiters to endText -- find the end one.
	set extracts to {}
	repeat with subText in liste
		if subText contains endText then
			copy text item 1 of subText to end of extracts
		end if
	end repeat
	set AppleScript's text item delimiters to tid -- back to original values.
	return extracts
end extractBetween

It returns the two available extracts.

{“mother has spanked me”, “'satiable curtiosity”}

Yvan KOENIG (VALLAURIS, France) mercredi 9 juin 2010 20:56:59

Hello Yvan.

Glad you spotted it Yvan. BRILLIANT. I took some liberties and revised your working code a little bit.
I changed the line

  set liste to text items 2 thru -1 of SearchText

to

set liste to text items of SearchText

I commented the setting of the second text item delimiter as well as I had to fiddle a little to understand how it worked.
I gave it a name as well: extractAllBetween() to make it differ from the other.
Sometimes I’m sure that there will be only one match between two delimiters.

I hope you forgive me.
This handler is BETTER than this:

echo "My father has spanked me, and my mother has spanked me; all my aunts and uncles have spanked me for my 'satiable curtiosity; and still I want to know what the Crocodile has for dinner" |sed -e 's/.*my//' -e 's/;.*//' 

As Yvans handler catches ALL occurrences between a start text and an end text, and the sed command line above does not.

I have stolen it as we speak :slight_smile: , the handler goes into my bag of tricks credited Yvan Koenig.



set t to "My father has spanked me, and my mother has spanked me; all my aunts and uncles have spanked me for my 'satiable curtiosity; and still I want to know what the Crocodile has for dinner!"
extractAllBetween(t, "my ", ";") ”> {"mother has spanked me","'satiable curtiosity"}

---- The handler ----
to extractAllBetween(SearchText, startText, endText)
	set tid to AppleScript's text item delimiters -- save them for later.
	set AppleScript's text item delimiters to startText -- find the first one.
	set liste to text items of SearchText
	set AppleScript's text item delimiters to endText -- find the end one.
	” causes "copy text item 1" to only copy text before the end text.
	set extracts to {}
	repeat with subText in liste
		if subText contains endText then
			copy text item 1 of subText to end of extracts
		end if
	end repeat
	set AppleScript's text item delimiters to tid -- back to original values.
	return extracts
end extractAllBetween


Best Regards

McUsr

This is the kind of support that makes me want to learn and give back to the macscripter community!

McUser - That script really helped since I wasn’t sure how to pass variables in automator. I ended up using the extractBetween handler.

Yvan - Really going one step beyond, thank you!

Everyone - thanks for your contributions to this thread!

This has helped turn my script into a monster and now I’ve run into an obstacle of a different nature so I will start a new thread.

Don’t worry.

We learnt things starting from what others did before us.

I’m sure that in my scripts, some pieces of code where already used here and there by others.
As years pass, it become difficult to know what is really our own code and what was, more or less, borrowed from pieces of code written by others.

Good luck.

Yvan KOENIG (VALLAURIS, France) vendredi 11 juin 2010 22:25:01

Hello

I think you should stick with Yvan’s version. As it is more correct.
It might be a tad harder to understand but operates more “logical”: If you require only one match between to tags; that match should
be the first one. This is the way all regexp tools work when only a match without any tagging of which match and so one is specified. You could call that handler extractFirstBetween.

If you just want the first hit, then exit from the repeat loop after first match and return the result.

Best Regards

McUsr