Skip to main content

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
Tech Talk

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
Tech Talk

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 isigned (positive or negative) decimal integer (# has no effect):

format("%4d", 27) —> " 27"

format("%+-4d", 27) —> "+27 "

format("%04i", 27) —> "0027"
uunsigned (must be positive) decimal integer (# has no effect):

format("%u", 27) —> "27"
ounsigned octal integer (# increases precision to force a leading zero):

format("%#o", 27) —> "033"
x or Xunsigned hexadecimal integer (# prepends ‘0x’ or ‘0X’ before a non-zero value):

format("%x", 27) —> "1b"

format("%#X", 27) —> "0X1B"
fsigned 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 Esigned 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 Gsigned 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"
csingle character

format("%-2c", "hello") —> "h"
stext string

format("%6s", "hello") —> "hello"

format("%-3.2s", ".2s", "hello") —> "he "
btext string with backslash escape sequences expanded

format("%b", "\tHello\\") —> " Hello\"
a or Asigned 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 either data or file.
  • file — the path to a file to be hashed. If you don't specify a dataValue, you must specify either data or file.
  • type — the type of hash to compute. The default value is “sha256”.
  • key — the key string for HMAC. If you include key, SenseTalk uses the HMAC algorithm for the calculation. If you omit key, 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
note

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.

Tech Talk

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"
Tech Talk

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 )

note

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"]
note

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"]
note

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 Options

Options:
[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"
Tech Talk

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.

note

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 aString

Function 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 aString

Function 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
Tech Talk

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
Tech Talk

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
Tech Talk

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:

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

note

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 )

note

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: