Text and Data Manipulation
SenseTalk has strong text handling capabilities. Its chunk expressions, described in Chunk Expressions, provide a powerful and intuitive means of accessing and manipulating specific portions of a text string. In addition, there are a number of commands and functions for obtaining information about text, converting between text and other data formats, and manipulating text at a high level. The commands and functions for performing these actions are described in detail below.
Capitalized
Function
Behavior: The capitalized
function returns text with the first letter of each word capitalized.
Syntax:
{the} capitalized of stringFactor
capitalized( stringExpr )
Example:
put capitalized of "now and then" --> "Now And Then"
Related:
CharToNum
Function
Behavior: Returns the numeric code (in Unicode) representing the first character of its parameter.
Syntax:
{the} charToNum of textFactor
charToNum( textExpr )
Example:
put charToNum("a") --> 97
Related:
Delete
Command
Behavior: The delete
command deletes a chunk of text or one or more occurrences of a target text string within a container. In its simplest form, it will delete every occurrence of the target text, regardless of case. Other forms allow you to specify a chunk by its location, or to tell how many occurrences of a target string—or even to indicate a particular occurrence—to delete, and to specify exact case matching.
Delete Chunk
This form of the delete
command will delete any chunk of text (characters, words, lines, or text items) from within a value. The chunk can be specified with any chunk expression describing the part of container that should be deleted. See Chunk Expressions for a full description.
Syntax:
delete chunk [of | in] container
Example:
set sentence to "In a hole in the ground there lived a hobbit."
delete words 2 to 4 of sentence
put sentence --> "In the ground there lived a hobbit."
Example:
delete the first 2 characters of line 15 of output
Example:
delete the first line of file manual
Delete Text or Pattern
This form of the delete
command will delete a target text value or pattern (see Pattern Language) from within a string. This form of delete
includes a number of variations which let you specify how many occurrences of the target—or even to indicate a particular occurrence—to delete, and to specify exact case matching.
Exactly one of the options defining the targetTextOrPattern must be supplied, as well as the container where the deletions will occur. The case options are optional. The options used may be specified in any order, although only one option of each type can be given.
Syntax:
delete {Options}
Options:
[in | within | from] container
{all {occurrences of} | every {occurrence of} } targetTextOrPattern
{the} [first | last] howMany {occurrences of} targetTextOrPattern
{the} ordinalTerm {occurrence of} targetTextOrPattern
occurrence ordinalNumber of targetTextOrPattern
[with | considering] case
[without | ignoring] case
Example:
delete "#" from text -- this will delete every occurrence of "#"
Example:
delete the last "s" in word 3 of sentence
Example:
delete all <punctuation or whitespace> from phoneNumber
Example:
delete every occurrence of "ugly" in manual
Example:
delete the third "i" within phrase considering case
You must include the in container or within container option in such a delete command. The container can be any container, including a variable, a portion of a variable (using a chunk expression), or a text file. If container is a variable, its contents may be of any sort, including a list or property list. The delete
command will delete the indicated text, searching through all values nested to any depth within such containers.
You must include one of the targetTextOrPattern options in a delete command, to specify what will be deleted. Simply providing a targetTextOrPattern expression will cause the command to delete every occurrence of the value of that expression within container, so use this option cautiously. You may optionally precede targetTextOrPattern by all {occurrences of} or every {occurrence of} in this case if you like, which makes the impact clearer.
If the first or last options are used, howMany will specify the number of occurrences of targetTextOrPattern that should be deleted, starting at either the beginning or end of container respectively.
If ordinalTerm or ordinalNumber is given, only a single occurrence of targetTextOrPattern will be deleted. The ordinalTerm should be an ordinal number, such as first
, second
, third
, and so forth, or one of the terms middle
(or mid
), penultimate
, last
, or any
. The ordinalNumber should be an expression which evaluates to a number. If it is negative, the delete
command will count backward from the end of container to determine which occurrence to delete.
If considering case is specified, only occurrences of targetTextOrPattern within container that match exactly will be considered for deletion. The default is to delete any occurrence of targetTextOrPattern regardless of case.
The delete
command sets a result (as returned by the result
function) that indicates the number of occurrences that were deleted.
Delete Values
In addition to deleting a value by position (such as delete item 3 of myList
), you can delete specific values from a list. This is done using an each expression. For example, to delete all occurrences of the word "at" from some text you would say delete each word of myText which is equal to "at"
. The values to delete are selected using the where (or which or whose) clause of the each expression, which provides a great deal of flexibility. So in addition to deleting chunks that are equal to a given value, you can use almost any criteria to select the items to be deleted.
Syntax:
delete each chunkType [of | in] sourceValue {where conditionWithEach | which operator value | whose propertyCondition}
Example
delete each item of addressList whose zip code is 80202
Example
delete each line of testCases where the last item of each is "failed"
Example
delete each item of scores which is equal to zero
Example
delete each line of file "entries" which is empty
Example
delete each item of subscriberList whose expirationDate is earlier than yesterday
Related:
ExcludeItems
Function
Behavior: The excludeItems
function returns a list containing all of the values from list1 that are not also present in list2. By default, this function follows the current setting of the caseSensitive
property.
Syntax:
the items of list1 excluding those in list2
excludeItems( list1, list2 )
Example:
put ["carrots","bananas","pistachios","lettuce","wasabi","aspirin","tissues"] into GroceryList
put ["cat food","tissues","aspirin","soda","socks"] into TargetList
put the items of GroceryList excluding those in TargetList --> [carrots,bananas,pistachios,lettuce,wasabi]
Related:
Format
Function
Behavior: Returns a formatted text representation of any number of values, as defined by a template string. The template consists of text intermixed with special formatting codes to specify such things as numbers formatted with a defined number of decimal places, text values formatted with extra spaces to fill a defined minimum length, and more.
Syntax:
format( template, value1, value2, ... )
Example:
set interestRate to 5.457
put format("The interest rate is %3.2f %%", interestRate) --> The interest rate is 5.46 %
Example:
format(reportTemplate, day(date), month(date), description, amount)
Example:
format("%x", maskValue) -- converts maskValue to hexadecimal
The template string can include any format codes supported by the standard Unix printf command, as summarized below. In addition, certain “escape sequences” beginning with a backslash character are translated as follows: \e
— escape character; \a
— bell character; \b
— backspace character; \f
— formfeed character; \n
— newline character; \r
— carriage return character; \t
— tab character; \v
— vertical tab character; \’
— single quote character; \\
— backslash character; \num
— character whose ASCII value is the 1-, 2-, or 3-digit octal number num.
A format code begins with a percent sign (%
) followed by optional modifiers to indicate the length and number of decimal places for that value, and ends with a letter (d
, i
, u
, o
, x
, X
, f
, e
, E
, g
, G
, b
, c
, s
, a
, A
, or @
) that specifies the type of formatting to be done (see the table below). Two percent signs in a row (%%
) can be used to produce a percent sign in the output string.
Following the percent sign, and before the letter code, a format may include a number indicating the output length for this value. The length may be followed by a decimal point (.
) and another number indicating the “precision” — this is the number of decimal places to display for a number, or the maximum number of characters to display from a string. Either the length or precision may be replaced by an asterisk (*
) to indicate that that value should be read from an additional parameter.
Before the length, the format code may also include any of the following modifier codes as needed:
- A minus sign (-) indicates the value should be left-aligned within the given length
- A plus sign (+) indicates that signed number formats should display a plus sign for positive numbers
- A space ( ) indicates that signed number formats should include an extra space for positive numbers
- A zero (0) indicates that leading zeros (rather than spaces) should be used to fill the specified length
- A pound sign (#) affects specific numeric formats in different ways as described below
The following table lists the format codes that are recognized, their meaning, and examples:
d or i | signed (positive or negative) decimal integer (# has no effect):format("%4d", 27) —> " 27" format("%+-4d", 27) —> "+27 " format("%04i", 27) —> "0027" |
u | unsigned (must be positive) decimal integer (# has no effect):format("%u", 27) —> "27" |
o | unsigned octal integer (# increases precision to force a leading zero):format("%#o", 27) —> "033" |
x or X | unsigned hexadecimal integer (# prepends ‘0x’ or ‘0X’ before a non-zero value):format("%x", 27) —> "1b" format("%#X", 27) —> "0X1B" |
f | signed fixed-precision number (# forces decimal point to appear, even when there are no digits to the right of the decimal point):format("%f", 27) —> "27.000000" (default precision is 6 decimal places) format("%7.3f", 27.6349) —> " 27.635" format("%+*.*f", 7, 2, 27.63" format("%#-5.0f", 27) —> "27. " |
e or E | signed number in exponential notation with 'e' or 'E' before the exponent (# forces decimal point to appear, even when there are no digits to the right of the decimal point)format("%e", 27) —> "2.700000e+01" format("%9.2E", 0.04567) —> "4.57E-02" |
g or G | signed number in fixed (the same as 'f') or exponential (the same as 'e' or 'E') notation, whichever gives full precision in less space (# forces decimal point to appear, even when there are no digits to the right of the decimal point; trailing zeros are not removed)format("%g", 27) —> "27" format("%+g", 0.04567) —> "+0.04567" |
c | single characterformat("%-2c", "hello") —> "h" |
s | text stringformat("%6s", "hello") —> "hello" format("%-3.2s", ".2s", "hello") —> "he " |
b | text string with backslash escape sequences expandedformat("%b", "\tHello\\") —> " Hello\" |
a or A | signed number printed in scientific notation with a leading 0x (or 0X) and one hexadecimal digit before the decimal point using a lowercase p (or uppercase P) to introduce the exponent (not available on Windows) |
@ | any value, displayed in its usual text format |
Related:
GloballyUniqueString
Function
Behavior: The globallyUniqueString
function generates a unique string each time it is called. Call globallyUniqueString()
to obtain a unique string to be used as an identifier, key, or file name. The value is unique across systems, application instances, and individual calls to the function. The returned value is a universally unique identifier string (UUID) conforming to the RFC 4122 standard.
Syntax:
the globallyUniqueString
globallyUniqueString( { formatNumber } )
GloballyUniqueString is usually called with no parameters, or with a parameter value of 0. If called with a formatNumber whose value is ‘1’, it returns a unique string in a form that is backward-compatible with older versions of SenseTalk (V2.13 and earlier) but does not conform to the RFC 4122 standard.
Example:
put globallyUniqueString() --> 95400D7C-35E8-47D0-9B72-F7854978D7A0
put globallyUniqueString(0) --> C9CF7512-07E8-4E14-8520-C251A08C3988
Example:
set part's code to the globallyUniqueString // give part a unique identifier
Hash
Function
Behavior: The hash
function returns a hash value for the given data. SenseTalk supports many hash types (industry-standard algorithms), as well as multiple output formats. This function can also produce a hash-based message authentication code (HMAC) based on the chosen hash type and supplied secret key.
Syntax:
hash( dataValue )
hash( dataValue, options ) hash( optionsIncludingDataOrFile )
The options or optionsIncludingDataOrFile is a property list that can include these properties:
data
— the data value to be hashed. If you don't specify a dataValue, you must specify eitherdata
orfile
.file
— the path to a file to be hashed. If you don't specify a dataValue, you must specify eitherdata
orfile
.type
— the type of hash to compute. The default value is “sha256”.key
— the key string for HMAC. If you includekey
, SenseTalk uses the HMAC algorithm for the calculation. If you omitkey
, SenseTalk computes a simple hash value.output
— the output format for the hash value. The default value is “Hex”.
The type
can be "sha1", "sha256", "sha384", "sha512", "sha3-224", "sha3-256", "sha3-384", "sha3-512", "md2", "md5", "ripemd128", "ripemd160", "ripemd256", or "ripemd320”. If you don't specify a type
, SenseTalk uses the default value “sha256”.
The output
may be any of "Base64", "modBase64", "base64url", "Base32", "Base58", "UU", "QP" (for quoted-printable), "URL" (for url-encoding), "Hex", "Q", "B", "url_oauth", "url_rfc1738", "url_rfc2396", "url_rfc3986", or "fingerprint”. If you omit output
, SenseTalk uses the default value “Hex”. Note that if you specify “hex” (with a lowercase “h”), SenseTalk returns a lowercase hex string rather than uppercase.
Example:
set sourceData to "Eggplant"
put hash(sourceData) --> 84247C8AAF6DD96FB2878483CB0140C23E3C12ABA8CC987306D0A77986286526
put hash(sourceData, type:"MD5") --> B2585BC3E070132D2BF51DFFAE794F64
put hash(data:sourceData, type:"MD5", output:"fingerprint") --> b2:58:5b:c3:e0:70:13:2d:2b:f5:1d:ff:ae:79:4f:64
Example:
set myFile to the temp folder & "fileToHash.txt"
put “Eggplant” into file myFile
put hash(file:myFile, type:"MD5") --> B2585BC3E070132D2BF51DFFAE794F64
Example:
set sourceData to "The quick brown fox jumps over the lazy dog"
put hash(sourceData, key:"1234") --> 214E68BDD7C12D03971AAA929226147AFC786448D239CAEC7ECEB6A39ADC2BCF
put hash(sourceData, key:"eggplant") --> A9F52CABD3FBEC4CD73C2CBEF44D711100A433F8C755AA0D542772E71B98926D
put hash(data:sourceData, type:"sha1", key:"eggplant") --> 29ED9AC3D1EC500E0103C2E3AE9D9D900B7A7637
Insert
Command, Push
Command
Behavior: Inserts a value or list of values at the end of a list, or before or after a specific item of the list.
Syntax:
[insert | push] expr {nested | item by item} [before | into | after] container
Example:
insert 5 into myList
Example:
push "hedgehog" into Animalia
Example:
insert newName before item index of nameList
Example:
insert [3,5] nested after pointList -- creates a nested list
Example:
insert "myBuddy" before my helpers
The push
command adds a value to the end of a list. The push
and pop
commands treat a list as a stack. Items pushed onto the stack can be retrieved in the reverse order with the pop
command. The push
and pull
commands treat a list as a queue. The pull
command retrieves items one at a time in the same order that they were added to the queue by the push
command.
Considering the insert
command syntax, expr is an expression whose value will be inserted into container. If before
is specified, the new value is inserted at the beginning of the list. If after
is specified, the new value is inserted at the end of the list. If into
is specified, the new value is inserted into the list at an appropriate position (currently always at the end of the list).
If container is specified as a particular item of a list (e.g. insert x after item 2 of myList
), the before
and after
options will insert the new value into the list before or after that item, respectively. The into
option, however, will treat that existing item as though it were the list being operated on. If it is a single value, it will become a list (nested within the main list), with the new value as its second item. If the targeted item was already a nested list, the new value will be inserted into that list.
If container is specified as a range of items in a list, the before
option will insert the new value before the first item in the range, and both the after
and into
options will insert the new value after the last item in the given range.
If expr yields a list of items rather than a single item, that list is inserted as a unit making a nested list if the nested
option was specified. If item by item
was specified each item from that list is inserted individually into the destination list. If neither option is specified, the type of insertion is controlled by the setting of the local property the listInsertionMode
if it has been set to either “nested” or “item by item”, or by the defaultListInsertionMode
global property, which is initially set to “item by item”.
The insert
or push
command never removes or replaces anything in the destination container. The container always becomes a list when something is inserted into it, even if it was empty or undefined to begin with.
Intersection
Function
Behavior: The intersection
function returns a list containing all of the values from list1 that are also present in list2. Any duplicate values are removed from the final list. By default, this function follows the current setting of the caseSensitive
property.
Syntax:
{the} intersection of list1 [and | with] list2
intersection( list1, list2 )
{the} [common | shared] [items | values] of list1 [and | with] list2
{the} [items | values] (that are) [shared by | ((shared) in) common [to | between]] list1 [and | with] list2
{the} [items | values] [of | in] list1 (that are) (also) [shared by | ((shared) in) common [to | with] | (found) in] list2
Example:
put ["carrots","bananas","pistachios","lettuce","wasabi","aspirin","tissues"] into GroceryList
put ["cat food","tissues","aspirin","soda","socks"] into TargetList
put the intersection of GroceryList and TargetList --> [aspirin,tissues]
Related:
Join
Command, Join
Function
Behavior: The join
command (or its synonym combine
) joins the items of a list, or the properties of a property list, into a single text value, using the specified delimiters. If the source value is a container, that container will receive the text string resulting from this command. If the source value is not a container, the variable it
will receive the text that results from combining the elements of the source value. The with quotes
option may be used to enclose each value in quotes.
When called as a function, join
(or combine
) returns the joined text value, for convenient use as part of an expression.
Command Syntax:
[join | combine] source {[using | with | by] listDelimiter {and keyDelimiter} {[using | with] quotes {quotes}}}Function Syntax:
[join | combine]( source {, listDelimiter {, keyDelimiter {, quotes} } } )
Example:
join [1,2,3] using ":" -- note: the source value is not a container
put it --> 1:2:3
Example:
combine [1,2,3] using ":" with quotes
put it --> "1":"2":"3"
Example:
put [1,2,3] into numbers -- start with a list in a container
join numbers using ":" with quotes ["<<",">>"]
put numbers --> <<1>>:<<2>>:<<3>>
Example:
combine {a:12,b:5} using ";" and "/"
put it --> a/12;b/5
Example:
join {a:12,b:5} with "##" using quotes -- only 1 delimiter
put it --> "12"##"5"
If source is a container (a variable), that variable becomes a text value with the results of the join operation. Otherwise, the variable it
receives the resulting text.
If source is a list, its items are combined using listDelimiter between the items. If source is a property list and only a listDelimiter is given, the property values are combined using listDelimiter between the values. If both keyDelimiter and listDelimiter are given, the result will contain the keys (property names) of each property before its value, using listDelimiter to separate each entry, and keyDelimiter to separate each key from its value within an entry.
If neither listDelimiter nor keyDelimiter is specified, the items or properties of source will be combined into a text string, using the current values of the listFormat.Separator
, the propertyListFormat.EntrySeparator
, and the propertyListFormat.KeySeparator
properties as appropriate. This applies to nested lists and property lists as well.
If using quotes
or with quotes
is specified, each value will be enclosed in quotation marks. If a quotes value is supplied, it is used instead of standard double quote marks. If quotes is a list, the first item will be used before each value, and the second item after each value.
Related:
KeepCharacters
Function
Behavior: Removes all characters from text except for alphanumeric characters or another set of characters that you specify. This function takes one or two parameters. The first parameter is the source text value to be filtered. The second (optional) parameter is a text string defining the set of characters that will be kept in the source text. If the second parameter is not given, letters and digits will be kept by default. Note that this function is case-sensitive.
Syntax:
keepCharacters( textExpr {, charactersToKeep} )
Example:
// Remove all characters except for e and s :
put keepCharacters("SenseTalk", "es") --> ese
Example:
This example shows how joined by empty
can be used to ensure that all characters are interpreted by KeepCharacters
as expected.
// This line puts the characters to keep into a variable so they can be passed to the KeepCharacters function later.
// Because of the use of 'joined by empty', they are stored as a text string:
// 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 '
put ("a".."z" &&& "A".."Z" &&& "0".."9" &&& space) joined by empty into CharstoKeep1
// This puts the characters to keep into a different variable for later use.
// Without 'joined by empty' they are stored as a list. When this list is passed to KeepCharacters, it is interpreted as a text string.
// That string includes all characters including square brackets, double quotes, and commas:
// '["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",0,1,2,3,4,5,6,7,8,9," "]'
put ("a".."z" &&& "A".."Z" &&& "0".."9" &&& space) into CharstoKeep2
// Passes CharstoKeep1 as a text string
put keepCharacters("Se@n[se-Ta^lk is, a gr*e]at l$angu~ag)e...!", CharstoKeep1) --> 'SenseTalk is a great language'
// Passes CharstoKeep2 (a list), which is interpreted by KeepCharacters as a string
put keepCharacters("Se@n[se-Ta^lk is, a gr*e]at l$angu~ag)e...!", CharstoKeep2) --> 'Sen[seTalk is, a gre]at language'
Length
Function
Behavior: Returns the number of characters in some text.
Syntax:
{the} length of textFactor
length( textExpr )
Example:
put length("SenseTalk") --> 9
Example:
if the length of name is less than 3 \
or the length of name is greater than 12 then
put "Invalid name!"
end if
Lowercase
Function
Behavior: The lowercase
function returns an expression converted to all lowercase (non-capital) letters.
Syntax:
{the} lowercase of stringFactor
lowercase( stringExpr )
toLower()
is a synonym for the lowercase()
function and can be used with the same syntax.
Example:
put lowercase of "Hi There!" --> "hi there!"
Example:
put "HELLO".toLower --> "hello"
Related:
Merge
Function
Behavior: Scans a source text and performs evaluation and substitution of expressions enclosed in merge delimiters, returning the merged text. The standard merge delimiters are double square brackets ([[
and ]]
). Any expressions within the source text enclosed in [[ and ]] are replaced by their value. Expressions are evaluated in the current context, so any local or global variables within a merge expression will have the same value they have in the handler which called the merge function.
In addition to simple expressions, the text between merge delimiters may include any SenseTalk statements. This can be very powerful, for such things as including repeat loops around portions of your text.
The last two parameters are optional: only a source string is required. If delimiter1 and delimiter2 are given, they are used in place of “[[“ and “]]” as the merge delimiters. If only delimiter1 is given, its value is used for both the opening and closing delimiters. If the evaluationContext
global property is set to Global
or Universal
, variables are treated as global or universal rather than local during the merge process.
The !
can be used before a quoted string as a shorthand for calling the merge
function.
Syntax:
merge( source {, delimiter1 {, delimiter2}} )
!" source "
Example:
put "Jorge" into name
put merge("Hello [[name]], how are you?") --> "Hello Jorge, how are you?"
Example:
put merge of "[[repeat with n=0 to 99]][[n]],[[end repeat]]" \
into numbersList
Example:
put ["cat", "dog", "rabbit", "fish"] into pets
put merge of "[[repeat with each item of pets]][[put it]][[end repeat]]"
--> cat
--> dog
--> rabbit
--> fish
Example:
put merge(template) into file "/Library/WebServer/Documents/report"
Example:
put "September" into monthName
put !"The month is now [[monthName]]" --> "The month is now September"
Number of
Operator
Behavior: This operator requires a literal number before the word of
, not a variable. This operator is useful for fractions of numbers and units. If the value is a number or a list, it is multiplied by the number. Otherwise, the of
operator will cause it to be repeated like the repeated operator.
Syntax:
fraction of aUnit
literalNumber of text {as {a} list}
literalNumber of numberOrList {as {a} list}
Example:
put three hundredths of an inch --> 0.03 inches
Example:
put five of "#" --> "#####"
Example:
put 12 of [1,2,3] --> [12,24,36]
Example:
put 3 of [a,b,c] as a list --> [a,b,c,a,b,c,a,b,c]
Example:
set the listInsertionMode to nested
put 3 of [a,b,c] as a list --> [[a,b,c],[a,b,c],[a,b,c]]
NumToChar
Function
Behavior: Returns the character represented by a given numeric code (in Unicode).
Syntax:
{the} numToChar of numFactor
numToChar( numExpr )
Example:
put numToChar(97) --> "a"
Related:
Offset
, Range
, EveryOffset
, EveryRange
Functions
Behavior: The offset
function returns the offset location of a target text within a source text, or the offset of a target value or list of values within a source list. The range
function works identically but returns the range (start and end locations) where the target is found in the source. If the target value being searched for is not found in the source, the number 0 (for offset) or empty range 0 to 0 is returned. Optional parameters to offset
or range
allow them to find occurrences of a substring beyond a certain point, to control whether the search is case-sensitive or not, and to search backward from the end of the source string.
Parameters: The beyondPosition, caseSensitive, and reverse parameters are optional: only a target string or value (to search for) and a source string or list (to search in) are required.
If beyondPosition is specified, the search will begin at the next character of the source string (or next item of the source list) beyond that position. To search from the beginning of the source, a value of zero should be used (the default). The value returned by the function is always the position (or range) where the target string was found within the source string, or zero if it was not found. If beyondPosition is given as a negative number, it indicates a position relative to the end of the source. In this case the return value will also be given as a negative number indicating the offset from the end of the source.
The caseSensitive parameter (if specified) should evaluate to true or false. If it is true, the search will only find exact case matches. The default (if not specified) is false. If the natural syntax is used, the search will be case sensitive if considering case
is specified and case insensitive if ignoring case
is specified. The default is to ignore case differences.
The reverse parameter (if specified) should evaluate to true or false. Using before in the natural syntax is equivalent to setting reverse to true. If it is true, a reverse search will be performed, starting at the end of the source (or at the character before beyondPosition) and searching toward the beginning. The default (if not specified) is false.
The everyOffset
and everyRange
functions work identically to their single counterparts, but return a list of all of the offsets or all of the ranges where the target is found within the source.
These functions are most commonly called using a natural English-like phrase rather than by calling them directly as detailed under Natural Syntax below.
Syntax:
offset( target, source )
offset( target, source, beyondPosition, caseSensitive, reverse )
range( target, source )
range( target, source, beyondPosition, caseSensitive, reverse )
everyOffset( target, source )
everyOffset( target, source, beyondPosition, caseSensitive, reverse )
everyRange( target, source )
everyRange( target, source, beyondPosition, caseSensitive, reverse )Natural Syntax:
{the | every} offset of targetFactor [in | within] sourceFactor
{ [before | after] [ { position | location } beyondPosition | {the} end ] }
{considering case | ignoring case}
{the | every} range of targetFactor [in | within] sourceFactor
{ [before | after] [ {position | location} beyondPosition | {the} end ] }
{considering case | ignoring case}
Example:
put offset("the", "Hi there!") --> 4
put range("the", "Hi there!") --> 4 to 6
put the range of "the" in "Hi there!" --> 4 to 6
Example:
get every offset of "eggs" within recipe
Example:
put offset ("th", "Hi there, from Thoughtful Software.", 5, FALSE)
--> 16 ("th" matches "Th" in Thoughtful)
put offset("th", "Hi there, from Thoughtful Software.", 5, TRUE)
--> 0 (case-sensitive, so not found, "th" does not match "Th", and search starts after the "th" in "there")
put offset of "th" within "Hi there, from Thoughtful Software" \
after 5 considering case --> 0 (same as above, using natural syntax)
put offset of "th" within "Hi there, from Thoughtful Software" \
before end --> 16 (backwards search)
put every offset of "th" within "Hi there, from Thoughtful Software" \
before end --> [16,4]
Example:
// Find the offset of all occurrences of ssn pattern match in textblock and place those positions into the ssnList list
set ssn to <3 digits then dash then 2 digits then dash then 4 digits>
put every offset of ssn in textblock into ssnList
Example:
put the range of "cat" in "concatenation" into catRange
put catRange --> 4 to 6
put chars catRange of "concatenation" --> "cat"
Example:
put the range of [c,d,e] in [a,b,c,d,e,f,g] --> 3 to 5
put the range of [c,d,e] in [a,b,c,d,X,e,f,g] --> 0 to 0
Example:
put the range of "money" in accounts after position lastFoundPos
Pop
Command
Behavior: The pop
command removes the last value from a list and stores it into a variable.
Parameters:
Syntax:
pop stackList into variable
pop item number of stackList into variable
Example:
put ["dog","cat","armadillo"] into Animalia
push "hedgehog" into Animalia
put Animalia --> ["dog","cat","armadillo","hedgehog"]
pop Animalia into Pets
put Pets --> "hedgehog"
put Animalia --> ["dog","cat","armadillo"]
put ["dog","cat","armadillo"] into Animalia
push "hedgehog" into Animalia
put Animalia --> ["dog","cat","armadillo","hedgehog"]
pop item two of Animalia into Pets
put Pets --> "cat"
put Animalia --> ["dog","armadillo","hedgehog"]
The push
and pop
commands treat a list as a stack. Items pushed onto the stack can be retrieved in the reverse order with the pop
command.
Related:
Pull
Command
Behavior: The pull
command removes the first value from a list and stores it into a variable.
Parameters: Optionally, you can specify which value to store into the variable.
Syntax:
pull from queueList into variable
pull item number of queueList into variable
Example:
put ["dog","cat","armadillo"] into Animalia
push "hedgehog" into Animalia
put Animalia --> ["dog","cat","armadillo","hedgehog"]
pull from Animalia into Pets
put Pets --> "dog"
put Animalia --> ["cat","armadillo","hedgehog"]
put ["dog","cat","armadillo"] into Animalia
push "hedgehog" into Animalia
put Animalia --> ["dog","cat","armadillo","hedgehog"]
pull item three of Animalia into Pets
put Pets --> "armadillo"
put Animalia --> ["dog","cat","hedgehog"]
The push
and pull
commands treat a list as a queue. The pull
command retrieves items one at a time in the same order that they were added to the queue by the push
command.
Related:
Replace
Command
Behavior: The replace
command replaces one or more occurrences of an old (target) text string within a container with a new (replacement) text string. In its simplest form, it will replace every occurrence of the old text with the new text, regardless of case. More advanced options allow you to specify how many occurrences — or even to indicate a particular occurrence — of the old text to replace, and to specify exact case matching.
Syntax:
replace OptionsOptions:
[in | within] container
{ all {occurrences of} | every {occurrence of} } oldText
{the} [first | last] howMany {occurrences of} oldText
{the} ordinalTerm {occurrence of} oldText
occurrence ordinalNumber of oldText
[with | by] newText
[with | considering] case
[without | ignoring] case
Example:
replace "Johnson" by "Johansson" in bigReport
Example:
replace the last "s" in word 3 of sentence with empty
Example:
replace every occurrence of " he " in manual with " she "
Example:
replace the first 2 "i" in phrase considering case by "I"
A number of options must be specified as part of the replace
command. Both oldText and newText must be supplied, as well as the container where the substitutions will occur. Other options are optional. The options may be specified in any order, although only one option of each type may be given.
You must include the in container or within container option in any replace command. The container can be any container, including a variable, a portion of a variable (using a chunk expression), or a text file. If container is a variable, its contents may be of any sort, including a list or property list. The replace
command will replace text in all values nested to any depth within such containers.
You must include the with newText or by newText option to supply the new text that will be substituted for the selected occurrences of the old text within the container.
You must include one of the oldText options in a replace command, to specify what will be replaced. Simply providing an oldText expression will cause the command to locate every occurrence of the value of that expression within container, and replace each one with the value of newText. You may optionally precede oldText by all {occurrences of} or every {occurrence of} if you like.
If the first or last options are used, howMany will specify the number of occurrences of oldText that should be replaced, starting at either the beginning or end of container respectively.
If ordinalTerm or ordinalNumber is given, only a single occurrence of oldText will be replaced by newText. The ordinalTerm should be an ordinal number, such as first
, second
, third
, and so forth, or one of the terms middle
(or mid
), penultimate
, last
, or any
. The ordinalNumber should be an expression which evaluates to a number. If it is negative, the replace
command will count backward from the end of container to determine which occurrence to replace.
If considering case is specified, only occurrences of oldText within container that match exactly will be considered for replacement. The default is to match regardless of case.
The replace
command sets a result (as returned by the result
function) that indicates the number of occurrences that were replaced.
Related: Chunk Expressions for other ways to replace portions of text.
Repeated
Operator
Behavior: Creates a string of text repeated a given number of times, up to a specified length, or creates a repeated list.
Syntax:
text repeated number times
value repeated number times as a list
text repeated to length number
a list of value repeated number times
Example:
put "$" repeated 12 times --> "$$$$$$$$$$$$"
Example:
put "Hello" repeated to length 12 --> "HelloHelloHe"
Example:
put "$" repeated 6 times as a list --> ["$","$","$","$","$","$"]
Example:
put a list of 7 repeated 3 times --> [7,7,7]
Reverse
Command, Reverse
Function
Behavior: The reverse
command reverses the order of the characters in a string, the items in a list, or reverses a range. If the value being reversed is not a list or a range, it is treated as a string and its characters are reversed. If the value being reversed is a variable or other container, the contents of the container are reversed in place. Otherwise, the reversed value is stored into the variable it.
When called as a function, reverse
returns the resulting list, range, or string for convenient use as part of an expression.
When reversing a range with a step by increment other than 1, the resulting range may have a different start value than the end value of the original range. This is done to preserve consistent behavior when the range is treated as a list. For example, the range 10 .. 20 by 5 when treated as a list will result in the list [10,15,20]. Reversing this range will result in 20 .. 10 by 5 which becomes [20,15,10] as a list. But the range 30 .. 42 by 5 as a list is [30,35,40]. Reversing this range gives the result 40 .. 30 by 5 (NOT 42..30 by 5) so that when treated as a list it will give the reverse of the original list, [40,35,30].
Command Syntax:
reverse stringRangeOrList
reverse {the} [words | lines | items] {delimited by delimiter} of aStringFunction Syntax:
reverse( stringRangeOrList )
{the} reverse of stringRangeOrList
stringRangeOrList reversed
Example:
put "alakazam" in reverse order --> "mazakala"
Example:
put 100 to 200 by 10 reversed --> 200 to 100 by 10
Example:
put the reverse of ["extreme", "high", "medium", "low", "trivial"] --> ["trivial","low","medium","high","extreme"]
Example:
reverse the words of "all men are created equal"
put it --> "equal created are men all"
Example:
reverse the lines of file "sonnet"
Related:
RTFToText
Function
Behavior: Converts rich text in the RTF format to plain text. The value of richText
should be text encoded in the RTF format. The rtfToText
function removes all of the formatting information and returns just the plain text contents from richText
.
Syntax:
{the} rtfToText of richText
rtfToText( richText )
Example:
put the rtfToText of file "Picasso.rtf" into picassoText
Shuffle
Command, Shuffle
Function
Behavior: The shuffle
command shuffles the characters in a string, or the items in a list, into a random order. If the value being shuffled is not a list, it is treated as a string. If the value being shuffled is a variable or other container, the contents of the container are shuffled in place. Otherwise, the shuffled value is stored into the variable it
.
When called as a function, shuffle
returns the resulting shuffled list or string for convenient use as part of an expression.
Command Syntax:
shuffle stringOrList
shuffle {the} [words | lines | items] {delimited by delimiter} of aStringFunction Syntax:
shuffle( stringOrList )
{the} shuffle of stringOrList
stringOrList shuffled
stringOrList in {a} [shuffled | random] order
Example:
put 1..6 shuffled --> [4,2,3,1,6,5]
Example:
shuffle the words of "we hold these truths to be self evident"
put it --> "evident these truths hold we to self be"
Example:
shuffle lotteryEntries
Example:
put ["aardvark","bear","coyote","dingo","elephant"] in a random order --> ["dingo","elephant","bear","coyote","aardvark"]
Example:
put shuffle("bluebeard") --> "ulberdeab"
Related:
Sort
Command, Sorted
Operator
Behavior: The sort
command sorts the contents of a container. The container's contents are replaced by the sorted contents.
The sorted
operator sorts the contents of a value, yielding the sorted value which can be stored into a container or used as part of a larger expression.
Syntax:
sort {Options} {by sortByExpr}
factor sorted {Options} {by sortByExpr}Options:
as chunkTypes // Only for the sorted operator
{{the} {[first | last] count} chunkTypes of } containerToSort // Only for the sort command
{in} [ascending | descending | increasing | decreasing | reverse | reversed] {order}
[numerically | {in} [numeric | numerical] {order} ]
[chronologically | {in} [dateTime | chronologic | chronological] {order} ]
[alphabetically | {in} [ text | alphabetic | alphabetical] {order} ]
[with | considering] case
[without | ignoring] case
Example:
sort nameList
sort ascending items delimited by tab of phoneList
Example:
sort the lines of file "scores" numerically \
in reverse order by the last item of each
Example:
sort the first 7 items of deck by each's rank
sort jobs by [city of each, salary of each]
put jobs sorted by [city of each, salary of each] into sortedJobs
put [99,3,2,5,32,36,45737,26] sorted --> [2,3,5,26,32,36,99,45737]
put randomList sorted as lines in ascending order into sortedList
A number of options may be specified as part of the sort
command. Only the containerToSort is required. The additional options are optional, and may be specified in any order, although only one sort order and one comparison type may be given.
If chunkTypes is specified, the sort will be performed on the chunks of that type (characters, words, text items, lines, or list items) within the containerToSort. If not specified, the items of the container will be sorted (either list items if it is a list, or text items). A delimiter may be specified for items, lines, or words.
If ascending or descending (or reversed) is specified, the result of the sort will be arranged by increasing or decreasing values, respectively. If the order is not specified, the sort will be performed in ascending order.
The comparison type used in the sort – whether numeric, alphabetic, or chronologic – can be indicated in several different ways. If the comparison type is not specified, the container will be sorted by comparing textual values, ignoring distinctions between uppercase and lowercase letters.
If numerically or one of its variant forms is specified, values are sorted based on their numeric values. If chronologically or one of its variants is specified, values are sorted by evaluating them as a particular time on a given date. Dates without specific times are treated as noon on that date. Times without dates are assumed to refer to the current date (today).
If alphabetically or one of its variants is specified (or if no comparison type is given) you may indicate whether or not case should be considered in the comparisons by specifying considering case or ignoring case.
Finally, if by sortByExpr is specified, it must come at the end of the command, following any other options. The sortByExpr is usually an expression involving the special variable each
which refers to each of the elements being sorted.
For example, if the variable nameList in your script contains a list of people’s names in which each name consists of a first name and a last name separated by a space, then sort the items of nameList
would sort the list alphabetically by the entire name of each person, resulting in a list in first-name order. The command sort the items of nameList by the last word of each
, however, would sort the list in order by last names.
When two or more elements being sorted have identical values, the sort
command leaves their order unchanged. This enables several sort commands to be used in sequence to do sub-sorting. Note that the sort operations must be done in reverse order, beginning with any sub-sorts, since the final sort will determine the primary order of the result. For example, given a list of objects representing people, where each object has both firstName
and lastName
properties, the following code will sort them into order by last name, and among those with the same last name, they will be sorted by first name:
sort people by the firstName of each
sort people by the lastName of each
Another way to do sub-sorting, with the only limitation being that every level of the sort is done in the same order (ascending or descending), is to sort by a list of elements, beginning with the primary element:
sort people by (the lastName of each, the firstName of each)
Related:
Split
Command, Split
Function
Behavior: The split
command splits text into a list of values, or into a property list of keys and values, by separating the text at specified delimiters. If the source value is a container, that container will become a list (or property list) as a result of this command. If the source value is not a container, the variable it
will receive the list (or property list) resulting from splitting the source value.
When called as a function, split
returns the resulting list or property list, for convenient use as part of an expression.
Command Syntax:
split sourceText {[by | using | with] listDelimiter {and keyDelimiter}}Function Syntax:
split( sourceText {, listDelimiter {, keyDelimiter}} )
Example:
split "apple;banana;orange;cherry" by ";"
put it --> {apple,banana,orange,cherry}
Example:
put "x=7;y=2" into coordinate
split coordinate using ";" and "="
put coordinate --> {x:7, y:2}
Example:
split "a/2, b/15, a/9" by ", " and "/"
put it --> {a:[2,9], b:15}
Example:
put split(filePath, "/") into pathComponents
If sourceText is a container (a variable), that variable becomes a list or property list containing the results of the split operation. Otherwise, the variable it
receives the resulting list or property list.
If listDelimiter is given, but keyDelimiter is not, the result will be a list, splitting the sourceText at each occurrence of listDelimiter to obtain the list items. If both keyDelimiter and listDelimiter are given, the result will be a property list, using listDelimiter to separate each entry, and keyDelimiter to separate each key from its value within an entry. If neither listDelimiter nor keyDelimiter is specified, the sourceText will be split into a list, using the current value of the itemDelimiter
property as the delimiter.
When creating a property list, if the same key occurs more than once in sourceText, the value associated with that key will become a list containing all of the values found for that key (see the final Example above).
Related:
StandardFormat
Function
Behavior: The standardFormat
function returns a text representation of any value, in a format suitable for archiving. For any type of value, this function should return a text value that can be supplied as the parameter to the value()
function to retrieve the original value.
Syntax:
{the} standardFormat of factor
standardFormat( expr )
Example:
put standardFormat(97) --> "97"
Example:
put the standardFormat of [1,"cow",2+3] --> ["1", "cow", "5"]
Example:
put standardFormat of {name:Jack, age:17} --> {age:"17", name:"Jack"}
Example:
put standardFormat(Jack & return & Jill) --> "Jack" & return & "Jill"
Example:
put standardFormat(Jack & quote & Jill) --> Jack"Jill
In general, standardFormat()
performs “Standard” quoting of values, and forces the use of standard formats for lists, property lists, and trees. However, you should not rely on the value returned by this function to always be in a specific format as the exact format may change from one version of SenseTalk to another, and might also depend on other factors, including the current internal representation of the value. It should always be true, though, that value(standardFormat(someValue))
is equal to someValue
.
Related:
Value
Functionthe defaultQuoteFormat
global propertythe listFormat
global propertythe propertyListFormat
global property- Conversion of Values.
Text
, AsText
Functions
Behavior: The text
function (or asText
) returns the value of its parameter in text format.
Syntax:
{the} text of factor
text( expr )
Example:
set the numberFormat to "00000"
put (4 * 13)'s text into formattedNumber --> "00052"
Related:
TextDifference
Function
Behavior: Calculates the "Levenshtein Distance" between two words or phrases. This is one measure of how different two text strings are from each other. If the two values are equal, their textDifference
will be zero. If one character must be changed to a different character, or one character inserted or deleted, in order to turn one string into the other, then the difference will be 1. A greater number indicates a greater difference between the two strings. The largest number that will be returned is the length of the longer string, which would indicate that the two strings are completely different. This function is not case sensitive, unless the caseSensitive
global property is set to true.
Syntax:
textDifference( string1, string2 )
Example:
put textDifference("Hobbit", "habit") --> 2
Example:
put textDifference("Hobbit", "hobo") --> 3
Example:
put textDifference("cheeseburger", "squash") --> 10
Trim
, TrimStart
, TrimEnd
, TrimAll
Functions
Behavior: Removes leading and trailing whitespace (or other characters) from a text value. Each of these functions takes one or two parameters. The first parameter is the source text value to be trimmed. The second (optional) parameter is a text string defining the set of characters that will be removed from the source text. If you omit the second parameter, whitespace and newline characters are trimmed by default.
The trim
function removes whitespace or specified characters from the beginning and end of the source text value.
The trimStart
function removes whitespace or specified characters from only the beginning of the source.
The trimEnd
function removes whitespace or specified characters from only the end of the source.
The trimAll
function removes all whitespace or specified characters from anywhere in the source text.
Syntax:
[trim | trimStart | trimEnd | trimAll]( textExpr {, charsToTrim} )
{the} [trim | trimStart | trimEnd | trimAll] of textExpr
If you want to remove whitespace as well as specific characters, you need to include a blank space with the character set in the second parameter.
Example:
put trim(" my words ") --> "my words" (With no second parameter, removes whitespace from beginning and end of source)
Example:
put trim(" my words ", "ms ") --> "y word" (Removes the characters m, s, and whitespace if found at the beginning and/or end of the source)
Example:
put trimStart(" my words ") --> "my words " (Removes whitespace from beginning of source)
Example:
put " my words ".trimEnd("ms ") --> " my word" (Removes the characters m, s, and whitespace if found at the end of the source)
Example:
put trim("mississippi", "i") --> "mississipp" (Removes the character i if found at the beginning and/or end of the source)
Example:
put trimall("mississippi", "i") --> "msssspp" (Removes all instances of the character i from the source)
Union
Function
Behavior: The union
function returns a list containing all of the values from list1 and all of the values from list2. Any duplicate values are removed from the final list. By default, this function follows the current setting of the caseSensitive
property.
Syntax:
{the} union of list1 [and | with] list2
union( list1, list2 )
Example:
put ["carrots","bananas","pistachios","lettuce","wasabi","aspirin","tissues"] into GroceryList
put ["cat food","tissues","aspirin","soda","socks"] into TargetList
put the union of GroceryList and TargetList --> [carrots,bananas,pistachios,lettuce,wasabi,aspirin,tissues,cat food,soda,socks]
Related:
UniqueItems
Function
Behavior: The uniqueItems
function returns a list containing all of the unique values from listValue, with any duplicates removed. By default, this function follows the current setting of the caseSensitive
property.
Syntax:
{the} unique items of listValue
uniqueItems( listValue )
Example:
put ["carrots","bananas","pistachios","lettuce","wasabi","aspirin","tissues","carrots","pistachios"] into GroceryList
put uniqueItems (GroceryList) --> [carrots,bananas,pistachios,lettuce,wasabi,aspirin,tissues]
Related:
Uppercase
Function
Behavior: The uppercase
function returns an expression converted to all uppercase (capital) letters.
Syntax: {the} uppercase of stringFactor
uppercase( stringFactor )
The toUpper
function is synonymous with the uppercase
function and can be used with the same syntax.
Example:
put uppercase("Hi There") --> "HI THERE!"
Related: