Removing leading and trailing space characters from string, plus a couple of text related questions

Here is one I stumbled upon that I do not understand at all but it seems to work reliably.

use scripting additions
set thet to "     Now is the time for all good men to come to the aid of the party     "
set qet to quoted form of thet
--> "'     Now is the time for all good men to come to the aid of the party     '"
-- alternate quoting also works
-- set qet to "\"" & thet & "\""
--> "\"     Now is the time for all good men to come to the aid of the party     \""

set cmd1 to "thet=" & qet & "; echo $thet"
--> "thet='     Now is the time for all good men to come to the aid of the party     '; echo $thet"

set out1 to do shell script cmd1
--> "Now is the time for all good men to come to the aid of the party"

Basically, I assign the quoted string to a variable and then echo the variable. Doesn’t seem to matter whether I use single or double quotes.

Of course. But what I was calling inefficient was to copy the shrinking string in a repeat loop

Pretty neat! :sunglasses:

Developing and foolproofing the idea a bit (ie. not relying on assumptions about words or punctuation), but still having fun with AppleScript syntax:

set theText to "                 … TIL “Now is the time for all good men to come to the aid of their party.” is a typing drill written by a teacher named Charles E. Weller. “Now is the time for all good men to come to the aid of their country.” is now used instead, because it exactly fills out a 70-space line. --u/tampared.     --Michael Scott;>? }                    "
-- set theText to "  !  "
-- set theText to "     "
-- set theText to ""
Trim(theText) --> "… TIL “Now is the time for all good men to come to the aid of their party.” is a typing drill written by a teacher named Charles E. Weller. “Now is the time for all good men to come to the aid of their country.” is now used instead, because it exactly fills out a 70-space line. --u/tampared.     --Michael Scott;>? }"

on Trim(theText)
	set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {space, tab, linefeed, return}} -- Add more white space delimiters if required.
	set {trimmedText, AppleScript's text item delimiters} to {theText's text items, ""}
	set trimmedText to trimmedText as text
	if ((count trimmedText) > 1) then
		tell trimmedText to tell {character 1, character -1} to set {{c1, c2}, AppleScript's text item delimiters} to {it, it}
		set trimmedText to c1 & theText's text from text item 2 to text item -2 & c2
	end if
	set AppleScript's text item delimiters to astid
	return trimmedText
end Trim
1 Like

Quote style in bash only affects value interpolation – since your text has no internal variables, it wouldn’t matter which you use.

x="bird"
y="It's a $x"   # "It's a bird"
z='It's a $x'   # 'It's a $x'

Your variation takes advantage of bash’s word splitting. But if you double-quote the echo’d variable instead of using it naked, you’d get your original argument back. Would be faster than mine though since you don’t need to create another process. Sweet as that would be even more obscure than mine version was! :rofl:

-- Mockman variation
on trimByWordSplitting(theText)
	return (do shell script "theText=\"" & theText & "\"; echo $theText")
end trimByWordSplitting

It also trims runs of any kind of white space within the string to single spaces.

I ran timing tests of the various alternatives with Script Geek on my M2 Mac mini. All results are in milliseconds:

Nigel One - 0.1 millisecond
Nigel Two - 0.3
Peavine - 0.3
Mockman One - 0.5
Robert - 0.1
Proebuck One - 9.0
Paul One - 0.1
Paul Two - 0.1
Mockman Two - 3.1
Nigel Three - 0.1
Proebuck Two - 3.3

FWIW, my basic AppleScript suggestion, which takes 0.1 millisecond:

set theText to "     Now is the time for all good me to come to the aid of the party     "
set trimmedText to trimWhitespace(theText)

on trimWhitespace(theText)
	repeat until text 1 of theText is not in {space, tab} --edit as desired
		set theText to text 2 thru -1 of theText
	end repeat
	repeat until text -1 of theText is not in {space, tab, linefeed} --edit as desired
		set theText to text 1 thru -2 of theText
	end repeat
end trimWhitespace

I’m surprised in that this script uses do shell script.

Could you retry the tests using @paulskinner’s string version (instead of the original) for both speed and correctness? Pretty sure only two actually work on anything difficult, though Nigel’s last post seems best.

Some of these seem to kinda cheat though, according to my prior experience. The input argument should not be changed, only a copy of it. This thinking assumes these type handlers should be functions, not procedures (using Pascal terminology).

Though slower, @Mockman and I would win for conciseness on the original string… :grin:

1 Like

I would suggest Nigels final Trim() version over mine. It’s preserving more text than my Trim() and he’s cleaning up after himself TIDS-wise.

The input value passed to the handler ( theText ) is local in the handler and not modified by the handler unless you do an assignment with the results

i.e.

set theText to Trim(theText)

While it’s entertaining to implement these methods, and looping is to be avoided where reasonable, I can’t imagine using any of these fun methods over trimming characters in a repeat loop. Which are all basically your xTalk command in AppleScript.

Simple and reliable, clear and direct, easy to debug but won’t need it for the previous reasons.

Thanks Mockman. I retested and I’ve corrected my earlier post.

proebuck. I had omitted Paul’s second script, and I’ve corrected that.

use framework "Foundation"
use scripting additions

property NSString : a reference to current application's NSString
property NSCharacterSet : a reference to current application's NSCharacterSet

set s to NSString's stringWithString:"     Now is the time for all good men to come to the aid of the party     "
set t to (s's stringByTrimmingCharactersInSet:(NSCharacterSet's whitespaceCharacterSet)) as text

Result:

“Now is the time for all good men to come to the aid of the party”

1 Like

Nvm. AppleScript handlers use pass-by-value for most arguments, including strings (which are pointers elsewhere). I also see that AppleScript works rather like Javascript and R in that the handler’s return value is that of the last statement if unspecified. While that’s not really surprising in and of itself, I was surprised that set would return the value it assigned. Still prefer a return statement to implicit return.

Just as a point of information, the two ASObjC suggestions operate differently. My stringByReplacingOccurrencesOfString suggestion (which I accidentally overwrote but see below) trims every paragraph of the string, while Nigel’s and VikingOSX’s stringByTrimmingCharactersInSet suggestion ignores paragraphs and trims the beginning and end of the string. One is not better then the other, although Nigel’s and VikingOXS’s suggestions are probably more responsive to Simon’s original request.

Well this is a thread that keeps on giving. Thanks all for taking so much interest.

I find Script Geek quite addictive and am pleased that it reports my initial attempt at a solution as being pretty quick to run.