Convert to lower case | error message

I have a simple line that used to reliably convert the contents of the clipboard to all lower case.

set the_list to (do shell script "echo " & quoted form of (get the clipboard) & " | tr [:upper:] [:lower:]")

It now only works sporadically.

Most of the time it gives me this error.

error "sh: -c: line 0: unexpected EOF while looking for matching `''
sh: -c: line 1: syntax error: unexpected end of file" number 2

Can anyone help?

Thanks

AppleScript: 2.5.1
Browser: Firefox 22.0
Operating System: Mac OS X (10.8)

Hi.

Your script works for me. But have you tried putting the ‘tr’ parameters in quotes?

set the_list to (do shell script "echo " & quoted form of (the clipboard) & " | tr '[:upper:]' '[:lower:]'")

I’m not sure what’s exactly goes wrong because your code works perfectly on my machine. However the error you’re getting is that the shell waits for an quote to turn on the substitution mode back on. In the shell you turn substitution mode on or off with a quote. When substitution mode is on all different characters have special meanings like a dollar sign, linefeed, semicolon and spaces for example, when substitution mode is off every character is considered as text and won’t be substituted except for the quote. When your substitution mode is off and reaches the end of the command, the end of the command came unexpected and the command expects at least a quote. I’ll hope this clears the “unexpected EOF while looking for matching `” error

Knowing what goes wrong we know it’s somewhere in the quotation of get the clipboard. I’m not sure why your command goes wrong, because it works perfectly on my machine, even with strings containing quotes. Maybe when you pipe the content directly in the tr command instead of using echo:

unexpected EOF while looking for matching:

set the_list to do shell script "tr '[:upper:]' '[:lower:]' <<<" & quoted form of (get the clipboard)

It’s a long shot but maybe worth trying (also it never harms to put arguments in quotes as well).

edit: Nigel’s post wasn’t there when I wrote this post


As an aside, ‘get’ shouldn’t be necessary with ‘the ciipboard’, which isn’t a reference to be resolved but a command returning a result.

It won’t harm either, the compiler will eventually create the same code; there is no difference in code, only in presentation.

Hello.

Maybe it is so, that the get is overseen, but I think the compiler to be stupid most of the times: If you write a statement, then the compiler, adds code for it. :slight_smile:

Edit

I wouldn’t count on get being over-seen before I saw there were no difference of compiled, (starting with size at first), since there are often a distinct difference in using get, and not, in some cases. None coming to mind as I write this.

I’ll hope that the compiler is a bit more intelligence than you suggest and it is. In the past I’ve done some research about how the compiler does code optimization and one of the things was hoping to finding out is how the compiler optimizes the code and guess what? Get is inserted if they’re not in there rather than being removed when not needed. You can test the code and I’ll bet that resulting code has the same hex value, or md5 hash, with and without using the get command. It seems that AppleScript is inserting missing code rather than it is removing unnecessary code. When you don’t wrap code in a run handler AppleScript will do that for you (exactly the same md5 hash as code in run handler without arguments).

Hello.

I am sure you are right in that, at least as long as the code we are talking about are outside and application tell block, because there exists cases, for instance when scripting mail on Snow Leopard, where a get makes a whole lot of difference, for getting various properties.

I have leveled down my impression of the AppleScript compiler as a smart one, and looks as rather simple, so when I hear that it inserts gets, then it improves the impression. :slight_smile:

And I know for sure that it doesn’t remove unecessary code, at least in some occasions. It does what it is told, which leads to greater file sizes, (and more statements to execute).

The harm is to the knowledge and ability of anyone who doesn’t realise that ‘the clipboard’ (two words) is a command in itself and that putting ‘get’ in front of it is wrong whether it causes an error or not. It may even mislead beginners reading this thread into thinking it’s what you have to do.

The likely reason for the ‘get’ having been included here is that the coder was thinking of the ‘clipboard’ (one word) as an object whose contents you either ‘get’ or ‘set’ ” whereas in fact the equivalent clipboard commands have multi-word names: ‘the clipboard’ (two words) and ‘set the clipboard to’ (four words). The ‘clipboard’ isn’t syntactically an object, just a word in the commands, the ‘the’ isn’t optional, and ‘set . to’ isn’t the ‘set’ command.

Knowing this, you’re less likely to write bad code which hangs around the Web for years embarrassing yourself and perpetuating the error, less likely to run into problems yourself, and less likely to offer bad advice to others.

I don’t point these things out just to be pedantic. :wink:

Thanks for your suggestions “ I shall experiment.

First of all I’m not defending myself here but the TS and all other user who prefer to use the get and the keywords more often than necessary and in front of commands. So they’ll know that they’re not writing bad code.

There is a difference in writing bad code or just another style. If you ask me this is just another style which I don’t use often but copied from the TS to keep in style. I agree with writers like Matt Neuberg and Dennis Goodman that the get keyword and the keyword can be freely used If you want to put the word get in the line of code to make it better readable. If it’s in front of a command, so be it. It’s one of the selling points of AppleScript, you can put words or hide them to turn your line of code into a proper English Sentence.

When I put the keyword the in front of a do shell script or get in front of the clipboard I don’t suggest that it’s included in the command. And we should also give some credits to the scriptwriters out there that they can see, based on the syntax highlighting, that there is a difference between keywords and commands.

Maybe this is just a point we’re not on the same line but working with many different coders on a daily base and seeing a lot of different styles of coding I’ve learned to make a difference in style differences and bad programming.

I don’t want to be pedantic as well, just reassure other writers who use extra keywords that they’re not writing bad code.

:cool:

As a non English user may discover this thread, I wish to say that it apply only for ASCII characters.

Other ones aren’t converted.

For see, try with “PÉNÉLOPE KÅ’NIG”

You will get the awful : “pÉnÉlope kÅ’nig”

This is why my choice is to use Python or ASObjC Runner

#=====
(*
Le second argument peut être: "upper", "lower", "title", "capitalize"
*)

on changecase(txt, mode)
	if mode is "upper" and txt contains "ß" then
		set oTIDs to AppleScript's text item delimiters
		set AppleScript's text item delimiters to "ß"
		set l to text items of txt
		set AppleScript's text item delimiters to character id 7838 -- or "SS"
		set txt to "" & l
		set AppleScript's text item delimiters to oTIDs
	end if
	set python_script to "import sys; print sys.argv[1].decode('utf8')." & mode & "().encode('utf8')"
	return do shell script "/usr/bin/python -c " & quoted form of python_script & " " & quoted form of txt
end changecase

#=====
(*
Le second argument peut être: "upper", "lower", "title", "capitalize"
*)

on change_case(txt, mode)
	if mode is "upper" and txt contains "ß" then
		set oTIDs to AppleScript's text item delimiters
		set AppleScript's text item delimiters to "ß"
		set l to text items of txt
		set AppleScript's text item delimiters to character id 7838 -- or "SS"
		set txt to "" & l
		set AppleScript's text item delimiters to oTIDs
	end if
	tell application "ASObjC Runner"
		if mode is "upper" then
			return modify string txt so it is caps
		else if mode is "lower" then
			return modify string txt so it is lower
		else if mode is "capitalize" then
			return modify string txt so it is cap words
		end if
	end tell
end change_case

#=====

KOENIG Yvan (VALLAURIS, France) jeudi 29 août 2013 17:41:00

Hi, back to Original Poster’s issue…
I don’t know the problem, but if you modify your code as follows then post the error result,
it will be easier for us all to pinpoint the problem rather than speculate…


try
	set the_list to (do shell script "echo " & quoted form of (get the clipboard) & " | tr [:upper:] [:lower:]")
on error
	tell application "TextEdit"
		make new document
		set text of document 1 to "echo " & quoted form of (get the clipboard) & " | tr [:upper:] [:lower:]"
	end tell
end try

That way we’ll all know what string pattern (** as seen by the shell **) has tripped a wire.

Model: PPC G4 Dual-800Mhz
AppleScript: 1.10.7
Browser: Safari 533.19.4
Operating System: Mac OS X (10.4)

Hello.

The erratic behaviour may very well have been quotes in the text on the clipboard, please do try this: :slight_smile:

It may be an overkill, but this parsing of the clipboard, should work with any do shell script command line you can imagine. (Please don’t prove me wrong. :wink: )

# set AppleScript's text item delimiters to ""
# set the clipboard to "Nik's \"BLOG\""
# set theText to the clipboard

set textWithEscapedQuotes to escapeQuotesInDoShellScriptInput for theText

set the_list to (do shell script "echo " & quoted form of textWithEscapedQuotes & " | tr [:upper:] [:lower:]")

set textWithUnescapedQuotes to unescapeQuotesFromDoShellScriptOutput for the_list

to unescapeQuotesFromDoShellScriptOutput for someText
	tell (a reference to text item delimiters)
		local originalTIDs, textWithUnescapedQuotes, temporaryVar
		set {originalTIDs, contents of it} to {contents of it, "\\\""}
		set temporaryVar to text items of someText
		set contents of it to "\""
		set textWithUnescapedQuotes to temporaryVar as text
		set contents of it to "\\'"
		set temporaryVar to text items of textWithUnescapedQuotes
		set contents of it to "'"
		set textWithUnescapedQuotes to temporaryVar as text
		set contents of it to originalTIDs
		# We reset the text item delimiters as we found them.
		return textWithUnescapedQuotes
	end tell
	
end unescapeQuotesFromDoShellScriptOutput

to escapeQuotesInDoShellScriptInput for someText
	tell (a reference to text item delimiters)
		local originalTIDs, textwithEscpaedQuotes, temporaryVar
		# we save the original text item delimiters, and sets them to '
		set {originalTIDs, contents of it} to {contents of it, "'"}
		set temporaryVar to text items of someText
		# we break down the text, to items between '
		set contents of it to "\\'"
		# we set new text item delimiters to \\'
		set textWithEscapedQuotes to temporaryVar as text
		# we reassemble the text with the new quotes.
		set contents of it to "\""
		# we repeat the steps for "
		set temporaryVar to text items of textWithEscapedQuotes
		set contents of it to "\\\""
		set textWithEscapedQuotes to temporaryVar as text
		# reassmbles he text
		set contents of it to originalTIDs
		# We reset the text item delimiters as we found them.
		return textWithEscapedQuotes
		# finally we return the text with escaped quotation mark.
	end tell
end escapeQuotesInDoShellScriptInput

I made two handlers from the original code above, and updated the post with it, as it is more reusable then, when you deal with the clipboard, and quotes, that may break the do shell script. This is mostly necessary if you echo the contents of a variable into a pipe. I think <<< ' & quoted form of input
should be a safe approach, but the circumstances isn’t always such, that this approach is feasible, therefore the handlers.

I recommend ASObjC Runner or Satimage OSAX, which both are considering diacritics

I agree with StefanK

But here is a quick and dirty way to roll your own, when you know what diacriticals you need to be able to handle,
as you can see, I have added æøå to the end of the ascii 7-bit alphabet, in the sed “translate” commands.

to makeUpper for sometext
	tell (do shell script "echo " & quoted form of sometext & "  | sed 'y/abcdefghijklmnopqrstuvwxyzæøå/ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ/'")
		return it
	end tell
end makeUpper

to makeLower for sometext
	tell (do shell script "echo " & quoted form of sometext & "  | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ/abcdefghijklmnopqrstuvwxyzæøå/'")
		return it
	end tell
end makeLower

For that, you don’t need sed, tr will do just fine:

do shell script "tr '[a-zöüä]' '[A-ZÖÜÄ]' <<<'erhältlich'"

Why build a script with a short subset of non ASCII characters when we may use existing tools able to treat every unicode characters.

I named ASObjCRunner and Python. Stephank added Satimage OSAX;

All of them make an excellent job.

KOENIG Yvan (VALLAURIS, France) samedi 31 août 2013 22:56:42

First of all because it’s possible and we show in many topics multiple ways to skin the cat, you can do this with php as well. Then some scriptwriters, including me, avoid the use of extra 3rd party software. So that means that there is only Python left to use for me. Then tr command does support multi byte characters, the problem that global variables [:upper:] and [:lower:] are simply equal to A-Z and a-z. So it’s not that tr is not supporting Unicode, it’s that, according to the Standards, those variables doesn’t contain extended characters. Then at last, tr is a lot (more than 10 times) faster than python.