Templates Containing Positional (Numeric) Patterns

A positional pattern is a number that identifies the character position at which the data in the source string is to be split. The number must be a whole number.

An absolute positional pattern is:

The number specifies the absolute character position at which the source string is to be split.

Here is a template with absolute positional patterns:

variable1 11 variable2 21 variable3

The numbers 11 and 21 are absolute positional patterns. The number 11 refers to the 11th position in the input string, 21 to the 21st position. This template puts characters:

Positional patterns are probably most useful for working with a file of records, such as:

The following example uses this record structure:

/* Parsing with absolute positional patterns in template         */
record.1="Clemens   Samuel    Mark Twain          "
record.2="Evans     Mary Ann  George Eliot        "
record.3="Munro     H.H.      Saki                "
do n=1 to 3
  parse var record.n lastname 11 firstname 21 pseudonym
  If lastname="Evans" & firstname="Mary Ann" then say "By George!"
end                         /* Says "By George!" after record 2  */

The source string is split at character position 11 and at position 21. The language processor assigns characters 1 to 10 to lastname, characters 11 to 20 to firstname, and characters 21 to 40 to pseudonym.

The template could have been:

1 lastname 11 firstname 21 pseudonym

instead of

lastname 11 firstname 21 pseudonym

Specifying 1 is optional.

Optionally, you can put an equal sign before a number in a template. An equal sign is the same as no sign before a number in a template. The number refers to a particular character position in the source string. These two templates are equal:

lastname  11 first  21 pseudonym
lastname =11 first =21 pseudonym

A relative positional pattern is a number with a plus (+) or minus (-) sign preceding it. It can also be a variable within parentheses, with a plus (+) or minus (-) sign preceding the left parenthesis; for details see Parsing with Variable Patterns.

The number specifies the relative character position at which the source string is to be split. The plus or minus indicates movement right or left, respectively, from the start of the string (for the first pattern) or from the position of the last match. The position of the last match is the first character of the last match. Here is the same example as for absolute positional patterns done with relative positional patterns:

/* Parsing with relative positional patterns in template         */
record.1="Clemens   Samuel    Mark Twain          "
record.2="Evans     Mary Ann  George Eliot        "
record.3="Munro     H.H.      Saki                "
do n=1 to 3
  parse var record.n lastname +10 firstname + 10 pseudonym
  If lastname="Evans" & firstname="Mary Ann" then say "By George!"
end                                             /* same results  */

Blanks between the sign and the number are insignificant. Therefore, +10 and + 10 have the same meaning. Note that +0 is a valid relative positional pattern.

Absolute and relative positional patterns are interchangeable except in the special case (Combining String and Positional Patterns) when a string pattern precedes a variable name and a positional pattern follows the variable name. The templates from the examples of absolute and relative positional patterns give the same results.

With positional patterns, a matching operation can back up to an earlier position in the source string. Here is an example using absolute positional patterns:

/* Backing up to an earlier position (with absolute positional)  */
string="astronomers"
parse var string 2 var1 4 1 var2 2 4 var3 5 11 var4
say string "study" var1||var2||var3||var4
/* Displays: "astronomers study stars"                           */

The absolute positional pattern 1 backs up to the first character in the source string.

With relative positional patterns, a number preceded by a minus sign backs up to an earlier position. Here is the same example using relative positional patterns:

/* Backing up to an earlier position (with relative positional)  */
string="astronomers"
parse var string 2 var1 +2 -3 var2 +1 +2 var3 +1 +6 var4
say string "study" var1||var2||var3||var4      /* same results   */

In the previous example, the relative positional pattern -3 backs up to the first character in the source string.

The templates in the previous two examples are equivalent.

You can use templates with positional patterns to make several assignments:

/* Making several assignments                                    */
books="Silas Marner, Felix Holt, Daniel Deronda, Middlemarch"
parse var books 1 Eliot 1 Evans
/* Assigns the (entire) value of books to Eliot and to Evans.    */

A length positional pattern is a number with a (>) or (<) preceding it. It can also be a variable within parentheses, with a (>) or (<) preceding the left parenthesis; for details see Parsing with Variable Patterns.

The number specifies the length at which the source string is to be split, relative to the current position.. The > or < indicates movement right or left, respectively, from the start of the string (for the first pattern) or from the position of the last match. The position of the last match is the first character of the last match. Here is the same example as for relative positional patterns done with length positional patterns:

/* Parsing with relative positional patterns in template         */
record.1="Clemens   Samuel    Mark Twain          "
record.2="Evans     Mary Ann  George Eliot        "
record.3="Munro     H.H.      Saki                "
do n=1 to 3
  parse var record.n lastname >10 firstname >10 pseudonym
  If lastname="Evans" & firstname="Mary Ann" then say "By George!"
end                                             /* same results  */

Blanks between the trigger and the number are insignificant. Therefore, >10 and > 10 have the same meaning. Note that >0 <0 and are valid length positional pattern.

The > length pattern and the + relative positional pattern are interchangeable except in the special case of the value 0. A >0 pattern will split the string into a null string and leave the match position unchanged. This is particularly useful for parsing off length-qualified fields from a string.

/* Parsing with length patterns in template         */
line = "04Mark0005Twain"
parse var line len +2 first >(len) len +2 middle >(len) len +2 last >(len)
say '"'first'" "'middle'" "'last'"'  -- displays "Mark" "" "Twain"

/* parsing with relative patterns only */
parse var line len +2 first +(len) len +2 middle +(len) len +2 last +(len)
say '"'first'" "'middle'" "'last'"'  -- displays "Mark" "05Twain" "Twain"

The < length pattern will move the position the indicated position to the left, and split the string between the original position and the movement position. At of the operation, the current position is returned to the original position. This movement is equivalent to using a negative relative pattern followed by a positive relative pattern for the same length. This operation allows for easy extraction of characters that precede a string match.

/* Parsing with length patterns in template         */
parse value '12345.6789' with '.' digit <1    -- digit -> "5"

/* parsing with relative patterns only */
parse value '12345.6789' with '.' -1 digit +1    -- digit -> "5"

Combining Patterns and Parsing into Words

If a template contains patterns that divide the source string into sections containing several words, string and positional patterns divide the source string into substrings. The language processor then applies a section of the template to each substring, following the rules for parsing into words.

/* Combining string pattern and parsing into words               */
name="    John      Q.   Public"
parse var name fn init "." ln        /* Assigns: fn="John"       */
/*          init="     Q"                                        */
/*          ln="   Public"                                       */

The pattern divides the template into two sections:

The matching pattern splits the source string into two substrings:

The language processor parses these substrings into words based on the appropriate template section.

John has three leading blanks. All are removed because parsing into words removes leading and trailing blanks except from the last variable.

Q has six leading blanks. Parsing removes one word-separator blank and keeps the rest because init is the last variable in that section of the template.

For the substring " Public", parsing assigns the entire string into ln without removing any blanks. This is because ln is the only variable in this section of the template. (For details about treatment of blanks, see Simple Templates for Parsing into Words.)

/* Combining positional patterns with parsing into words         */
string="R E X X"
parse var string var1 var2 4 var3 6 var4   /* Assigns: var1="R"  */
/*          var2="E"                                             */
/*          var3=" X"                                            */
/*          var4=" X"                                            */

The pattern divides the template into three sections:

The matching patterns split the source string into three substrings that are individually parsed into words:

The variable var1 receives "R"; var2 receives "E". Both var3 and var4 receive " X" (with a blank before the X) because each is the only variable in its section of the template. (For details on treatment of blanks, see Simple Templates for Parsing into Words.)