Seeking Code Efficiency--File GREP Routines

I want to fine-tune some handlers I use as part of a larger script and it was suggested I break-down my requests on a handler-by-handler basis if possible. What I’m seeking is better ways to do these things if possible. I’m not interested in exercises in “do this all in one line of code” (that stuff is cool, but hard to comment and troubleshoot in my environment), just general efficiencies.

These two handlers search a given file’s “innards” for one or more strings supplied as a list. The sub-handler is required to get around a bug in GREP returns to AppleScript…when GREP returns zero, AppleScript gets an error. Using a sub-handler allowed graceful managing of the error.

Thanks in advance for any help provided, of course!

-- Uses GREP to look into file looking for header string to identify file
--
on grepForString(path_to_grep, search_list)
	my logMe("BEGIN grepForString Handler", 3)
	
	repeat with current_grep_item in search_list
		try
			set grep_result to grepMe(path_to_grep, current_grep_item)
			exit repeat
		on error
			set grep_result to 0
		end try
	end repeat
	
	if grep_result = 0 then
		set current_grep_item to "<nothing found>"
	end if
	
	my logMe("¢ RETURN: " & grep_result & "x | " & current_grep_item, 3)
	my logMe("END grepForString Handler", 3)
	
	return {grep_result, current_grep_item as Unicode text}
	
end grepForString


-- Uses GREP to parse a single instance for grepForString
-- Sub-handling this gets around AppleScript problem when GREP returns zero
--
on grepMe(file_path, search_item)
	set file_path_POSIX to POSIX path of file_path
	set shell_string to ("grep -ch \"" & search_item & "\" " & quoted form of file_path_POSIX)
	return (do shell script shell_string)
end grepMe

Does this work for you?

on grep(patternList, filePath)
	--my logMe("BEGIN grepForString Handler", 3)
	
	repeat with pattern in patternList
		try
			do shell script "/usr/bin/grep --count " & quoted form of pattern & " " & quoted form of filePath
			set grepResult to result
			exit repeat
		on error errMsg number errNum
			if errMsg is "0" then
				-- grep didn't find anything
				set grepResult to 0
			else
				-- pass on the error
				error errMsg number errNum
			end if
		end try
	end repeat
	
	if grepResult is 0 then set pattern to "<nothing found>"
	
	--my logMe("¢ RETURN: " & grepResult & "x | " & pattern, 3)
	--my logMe("END grepForString Handler", 3)
	
	return {grepResult, contents of pattern}
end grep

-- Example
choose file without invisibles
grep({"Hello"}, POSIX path of result)

I used contents of pattern instead of a coercion to avoid changing string patterns to another class. (Also, I removed the -h option for grep because you’re not searching multiple files.)

Since you didn’t use the same variable names, I had to “convert” yours to marry it to my script, thusly:

on grepForString(path_to_grep, search_list)
	my logMe("BEGIN grepForString Handler", 3)
	
	repeat with current_grep_item in search_list
		try
			do shell script "/usr/bin/grep --count " & quoted form of current_grep_item & " " & quoted form of path_to_grep
			set grep_result to result
			exit repeat
		on error error_message number error_number
			if error_message is "0" then
				-- grep didn't find anything
				set grep_result to 0
			else
				-- pass on the error
				error error_message number error_number
			end if
		end try
	end repeat
	
	if grep_result is 0 then set current_grep_item to "<nothing found>"
	
	my logMe("¢ RETURN: " & grep_result & "x | " & current_grep_item, 3)
	my logMe("END grepForString Handler", 3)
	
	return {grep_result, contents of current_grep_item}
end grepForString

Unfortunately, I got an error involving “Can’t make quoted form of item 1 of (alias…

My first guess is it’s an input problem with the “path_to_grep”…quick check of my script (available in another thread if you need to look for yourself) shows I seem to be passing around the alias/references directly from files dropped onto the script (it’s saved as a droplet/applet for drag-n-drop use). Perhaps my original script posted in this thread will give some clues too?

I had to do a double take, but I see what the problem is. In your first script, you were getting the POSIX path in your grepMe handler; In you second script, you never get the POSIX path, which means you’re trying to get the quoted form of an alias, which isn’t possible (thus the error). (Note that I passed the POSIX path to handler in my example.)

At the risk of sounding extremely naïve…how do I fix the problem?

I would get the POSIX path when you call the handler.

on open theseItems
	repeat with thisItem in theseItems
		grepForString(POSIX path of thisItem, {"example"})
	end repeat
end open

Is there any handy way to do this within grepForString? It would be and easier change to make and centralize the “coersion.” I use this handler alot and wouldn’t look forward to changing everyplace I call the handler. =O.o=

I’ve been trying to get into the habit of keeping the references returned from a droplet “as is” until they get into handlers. I’ve found doing on-the-fly or differing “coersions” at the “top level” of the script very confusing and I quickly lose track of what “form” a file reference is in (reference, POSIX path, alias, string, etc.).

Hope that makes sense…

I know I had some decent logic as to why I did it the way I did it, but now I actually I think it would be better to include it in the handler.

do shell script "/usr/bin/grep --count " & quoted form of current_grep_item & " " & quoted form of POSIX path of path_to_grep

Side note: On Mac OS X 10.4 (AppleScript 1.10) or later, you can safely pass a POSIX path to this handler as well (for future reference).

Huzzah!

That did the trick. Can’t tell whether it’s more efficient, but it is more straightforward than the 2-handler method I was using.

THANKS!