I wonder if it is possible for a script to do something if a character (for example the 16th) in a filename (in my case) is a #
Example:
AL0603-020-020-#johanTESTAR
Regards / Johan
I wonder if it is possible for a script to do something if a character (for example the 16th) in a filename (in my case) is a #
Example:
AL0603-020-020-#johanTESTAR
Regards / Johan
Perhaps something like this:
set Str_1 to "AL0603-020-020-#johanTESTAR"
set {TID, text item delimiters} to {text item delimiters, "#"}
if length of text item 1 of Str_1 is 15 then
return true
else
return false
end if
set text item delimiters to TID
Doesn’t work, of course, if there are other “#” characters before the one you want, i.e. count of text items of Str_1 > 2, but that would be easy to work in.
Crazy quick replies here
Thanks Adam, that should work for me, I’ll try it out!
But - why the “set text item delimiters to TID” at the end???
This forum rocks!!!
Regards / Johan
Here is a different approach:
set t to "AL0603-020-020-#johanTESTAR"
character 16 of t is "#" --> true
VERY VERY important. If you set AppleScript’s TIDs to something (they are normally “”), AppleScript remembers that and will screw you up the next time you want to manipulate a string. Whenever you set them for some reason, set them back the way you found them when you are done. The first set {TID, text item delimiters} to {text item delimiters, “#”} is equivalent (and a shorter way) to say:
set TID to AppleScript's text item delimiters -- remember how you found them
set AppleScript's text item delimiters to "#" -- set them as you need them here
-- do your stuff
set AppleScript's text item delimiters to TID -- this sets them back as they were, whatever they were coming in.
Help! I’m in the middle of a admin-war…
Thanks jj, seems even simpler than Adams
OK, now I understand how text item delimiters work, I learn something new here every day, thanks Adam!!
Regards / Johan
(Still hasn’t been able to make it work in my script, but working on it!)
It’s running soooo nicely now, thanks again to both of you! (wont tell you wich one I used
Regards / Johan
You should be using jj’s - it’s much more efficient. When there are lots of ways to do something, the simplest doesn’t always occur to you. Text item delimiters aren’t necessary for this, but they are a very powerful tool in the AppleScript toolbox.
I did use the simple approach, but I’m glad I got a lesson in text item delimiters on the way there, didn’t really understand how it worked before, much clearer now, still have tons to learn, but to put it in another way:
say “it’s more fun to compute” using “Ralph”
(the ending of all my applescripts
Regards / Johan
http://www.krautrockgroup.com/Audio/KraftwerkCOMPUTER7.mp3
You can also do something like this:
set theString to "Hello How are you you? are you feeling #fine?"
set numLocations to {}
repeat with with i from 1 to (count theString)
if (character i in theString) is "#" then
set numLocations to numLocations & i
end if
end
numLocations
That way it would return all of the locations of the “#” signs.
Good luck
Fortunately, we don’t do wars around here, KRAFTWERK - and I’m sure we’d all agree that it’s healthy to explore a range of possible options (including the pluses and pitfalls of each).
In that spirit, I hope nobody will mind if I chip in with one or two brief* observations on the subject…
(* And, as those who know me will attest, when I say brief, I really mean brief. ;))
AppleScript’s text item delimiters
It’s good to know that you’ve learned something about AppleScript’s text item delimiters from Adam’s helpful advice. They can be incredibly useful in certain text manipulations - and, in spite of requiring a few lines of code when using them, you’ll find they’re pretty fast, too.
It might be worth mentioning that the initial value of text item delimiters (sometimes misleadingly referred to as their “default” value) is actually a single-item list containing an empty string: {“”}. (I suspect Apple’s original plan was to add a way to use more than a single delimiter - although, if this is the case, it certainly hasn’t been implemented yet.) As things stand, it seems to matter little whether you use the list or the string form.
It may also help to clarify that the scope of the current value is limited to the current “session”. For example, any script run from Script Editor will be subject to the same tid value, whatever it might be at any time, and whichever SE script sets it. A script application will have its own tid value - which is set (and will consequently affect certain operations) from within that app only.
The principle of initially storing the current value before a tid-based operation, and then restoring it afterwards, is just a matter of safe practice. While it may not seem too critical in short, simple scripts, it can avoid some serious headaches in more complex routines (perhaps involving various handlers and subroutines). So it’s a habit worth developing.
It’s important to be mindful of situations in which a statement that restores the original tid value might be inadvertently skipped. One good example of this is within a try block.
Check out the results of this, for example:
to getName from currentData
try
set tid to text item delimiters
set text item delimiters to "name:"
set extractedName to currentData's text item 2
set text item delimiters to tid
set currentResponse to "This person's name is " & extractedName & "."
on error
set currentResponse to "Error: could not find this person's name."
end try
display dialog currentResponse giving up after 1
{|input data|:currentData, |tids restored?|:tid = text item delimiters} (* to help check results only *)
end getName
set resultList to {}
repeat with currentData in {"name:Bart Simpson", "town:Springfield"}
set resultList's end to getName from currentData's contents
end repeat
set text item delimiters to {""} (* restore initial value *)
resultList
--> {{|input data|:"name:Bart Simpson", |tids restored?|:true}, {|input data|:"town:Springfield", |tids restored?|:false}}
From this, we can see that the first entry (“name:Bart Simpson”) succeeded, and the tid value was restored as expected. However, the second entry (“town:Springfield”) resulted in an error - since it didn’t contain the string “name:”. Because of this, the tid value wasn’t restored. i[/i]
What we should have done is include, within the error statement itself, an additional statement - to restore the original tid value when an error occurs:
on error
set text item delimiters to tid
set currentResponse to "Error: could not find this person's name."
end try
So the script should now return:
--> {{|input data|:"name:Bart Simpson", |tids restored?|:true}, {|input data|:"town:Springfield", |tids restored?|:true}}
(Computers can do that?)
Other examples of such potential traps include ‘exit repeat’ and ‘return’ statements. The script suggested earlier, for instance, might be improved with a construct something like this:
set t to "AL0603-020-020-#johanTESTAR"
set tid to text item delimiters
set text item delimiters to "#"
set b to (count t's text item 1) is 15
set text item delimiters to tid
b
--> true
Choosing a solution
OK, so you’ve already decided on your preference in this case, and that’s cool. Nevertheless, I hope folks will forgive me for dwelling on the decision-making process for a moment…
Making a choice between different methods may depend on individual circumstances. To weigh up the pros and cons of a particular approach, I sometimes find myself using an almost subconscious “points” system. (Of course, the weight given to each of these so-called “points” is strongly influenced by the nature of the task in hand.) Typical considerations, some of which may be mutually exclusive, could include (in no particular order - apart from the first one):
To make for a more interesting comparison, let’s say that - in response to the original question - I threw in yet another option:
set t to "AL0603-020-020-#johanTESTAR"
(offset of "#" in t) is 16 --> true
So, in this particular context, how do these three approaches (‘tid’, ‘character’ and ‘offset’) stack up together?
Well, they all work pretty well - and are likely to do so on quite a range of machines - as long as the length and general format of the input string doesn’t vary significantly from the example used. The ‘offset’ and ‘tid’ methods should generally work on strings of any length - although the tid-based routines would return incorrect results if the input string happens to be exactly 15 characters in length. The ‘character’ method, on the other hand, needs only a small tweak to avoid an error on strings of less than 16 characters (if that’s considered a possibility):
set t to "AL0603-020-020-#johanTESTAR"
(count t) > 15 and character 16 of t is "#" --> true
However, both ‘offset’ and ‘tid’ might fall down more seriously if character 16 was indeed “#” - and the same character also appeared anywhere within the first 15 characters of the string. In such a situation, the results returned would be incorrect - so some additional work would be needed to resolve this.
In terms of speed, all suggestions are pretty fast - given that the task is a pretty small one, anyway. There is a performance spread, with the ‘character’ method leading - and my makeweight effort, ‘offset’, bringing up the rear. (For the curious: on an indexed scale where 1 = the fastest time, the averaged results here are: character:1.00, tid(2):1.25, tid(1):1.57, offset:1.62.)
OK then - so what about code length and comprehensibility? Well, though I’m a keen fan of text item delimiters, I can’t pretend that a tid-based routine is ever going to win in the brevity stakes (not against this competition and in this context, anyway). And I’m not entirely convinced that everyone finds them that easy to follow, either. The ‘offset’ alternative is short and straightforward enough (as long as one already understands “offset” as “position”). But I’m pretty confident that even a rank newcomer would stand a good chance of working out what character 16 of t is “#” is supposed to mean.
Now… c’mon, kai - it’s make-your-mind-up time. Weighing up all the current and potential issues, which method would you choose for the job?
Ah… once again, I may have said too much already. So I’ll just offer my usual apologies for “going on a bit” - and perhaps leave that question as an exercise for the reader…
WOW! Been away for a while, and comes back to this, great explanation Kai, this should be in a sticky thread, thanks for the lesson!
Regards / Johan (My script runs flawlessly…