The value of a scalar or integer parameter may also be assigned by writing:
name=value
If the integer attribute, -i, is set for name, the value is subject to arithmetic evaluation. Furthermore, by replacing `=' with `+=', a parameter can be added or appended to. See the section `Array Parameters' for additional forms of assignment.
To refer to the value of a parameter, write `$name' or `${name}'. See Parameter Expansion in zshexpn(1) for complete details.
In the parameter lists that follow, the mark `<S>' indicates that the parameter is special. Special parameters cannot have their type changed or their readonly attribute turned off, and if a special parameter is unset, then later recreated, the special properties will be retained. `<Z>' indicates that the parameter does not exist when the shell initializes in sh or ksh emulation mode.
set -A name value ...
name=(value ...)
If no parameter name exists, an ordinary array parameter is created. If the parameter name exists and is a scalar, it is replaced by a new array. Ordinary array parameters may also be explicitly declared with:
typeset -a name
Associative arrays must be declared before assignment, by using:
typeset -A name
When name refers to an associative array, the list in an assignment is interpreted as alternating keys and values:
set -A name key value ...
name=(key value ...)
Every key must have a value in this case. Note that this assigns to the entire array, deleting any elements that do not appear in the list.
To create an empty array (including associative arrays), use one of:
set -A name
name=()
Individual elements of an array may be selected using a subscript. A subscript of the form `[exp]' selects the single element exp, where exp is an arithmetic expression which will be subject to arithmetic expansion as if it were surrounded by `$((...))'. The elements are numbered beginning with 1, unless the KSH_ARRAYS option is set in which case they are numbered from zero.
Subscripts may be used inside braces used to delimit a parameter name, thus `${foo[2]}' is equivalent to `$foo[2]'. If the KSH_ARRAYS option is set, the braced form is the only one that works, as bracketed expressions otherwise are not treated as subscripts.
The same subscripting syntax is used for associative arrays, except that no arithmetic expansion is applied to exp. However, the parsing rules for arithmetic expressions still apply, which affects the way that certain special characters must be protected from interpretation. See Subscript Parsing below for details.
A subscript of the form `[*]' or `[@]' evaluates to all elements of an array; there is no difference between the two except when they appear within double quotes. `"$foo[*]"' evaluates to `"$foo[1] $foo[2] ..."', whereas `"$foo[@]"' evaluates to `"$foo[1]" "$foo[2]" ...'. For associative arrays, `[*]' or `[@]' evaluate to all the values, in no particular order. Note that this does not substitute the keys; see the documentation for the `k' flag under Parameter Expansion Flags in zshexpn(1) for complete details. When an array parameter is referenced as `$name' (with no subscript) it evaluates to `$name[*]', unless the KSH_ARRAYS option is set in which case it evaluates to `${name[0]}' (for an associative array, this means the value of the key `0', which may not exist even if there are values for other keys).
A subscript of the form `[exp1,exp2]' selects all elements in the range exp1 to exp2, inclusive. (Associative arrays are unordered, and so do not support ranges.) If one of the subscripts evaluates to a negative number, say -n, then the nth element from the end of the array is used. Thus `$foo[-3]' is the third element from the end of the array foo, and `$foo[1,-1]' is the same as `$foo[*]'.
Subscripting may also be performed on non-array values, in which case the subscripts specify a substring to be extracted. For example, if FOO is set to `foobar', then `echo $FOO[2,5]' prints `ooba'.
A subscript may be used on the left side of an assignment like so:
name[exp]=value
In this form of assignment the element or range specified by exp is replaced by the expression on the right side. An array (but not an associative array) may be created by assignment to a range or element. Arrays do not nest, so assigning a parenthesized list of values to an element or range changes the number of elements in the array, shifting the other elements to accommodate the new values. (This is not supported for associative arrays.)
This syntax also works as an argument to the typeset command:
typeset "name[exp]"=value
The value may not be a parenthesized list in this case; only single-element assignments may be made with typeset. Note that quotes are necessary in this case to prevent the brackets from being interpreted as filename generation operators. The noglob precommand modifier could be used instead.
To delete an element of an ordinary array, assign `()' to that element. To delete an element of an associative array, use the unset command:
unset "name[exp]"
If the opening bracket, or the comma in a range, in any subscript expression is directly followed by an opening parenthesis, the string up to the matching closing one is considered to be a list of flags, as in `name[(flags)exp]'. The flags currently understood are:
See Parameter Expansion Flags (zshexpn(1)) for additional ways to manipulate the results of array subscripting.
This discussion applies mainly to associative array key strings and to patterns used for reverse subscripting (the `r', `R', `i', etc. flags), but it may also affect parameter substitutions that appear as part of an arithmetic expression in an ordinary subscript.
It is possible to avoid the use of subscripts in assignments to associative array elements by using the syntax:
aa+=('key with "*strange*" characters' 'value string')
This adds a new key/value pair if the key is not already present, and replaces the value for the existing key if it is.
The basic rule to remember when writing a subscript expression is that all text between the opening `[' and the closing `]' is interpreted as if it were in double quotes (see zshmisc(1)). However, unlike double quotes which normally cannot nest, subscript expressions may appear inside double-quoted strings or inside other subscript expressions (or both!), so the rules have two important differences.
The first difference is that brackets (`[' and `]') must appear as balanced pairs in a subscript expression unless they are preceded by a backslash (`\'). Therefore, within a subscript expression (and unlike true double-quoting) the sequence `\[' becomes `[', and similarly `\]' becomes `]'. This applies even in cases where a backslash is not normally required; for example, the pattern `[^[]' (to match any character other than an open bracket) should be written `[^\[]' in a reverse-subscript pattern. However, note that `\[^\[\]' and even `\[^[]' mean the same thing, because backslashes are always stripped when they appear before brackets!
The same rule applies to parentheses (`(' and `)') and braces (`{' and `}'): they must appear either in balanced pairs or preceded by a backslash, and backslashes that protect parentheses or braces are removed during parsing. This is because parameter expansions may be surrounded balanced braces, and subscript flags are introduced by balanced parenthesis.
The second difference is that a double-quote (`"') may appear as part of a subscript expression without being preceded by a backslash, and therefore that the two characters `\"' remain as two characters in the subscript (in true double-quoting, `\"' becomes `"'). However, because of the standard shell quoting rules, any double-quotes that appear must occur in balanced pairs unless preceded by a backslash. This makes it more difficult to write a subscript expression that contains an odd number of double-quote characters, but the reason for this difference is so that when a subscript expression appears inside true double-quotes, one can still write `\"' (rather than `\\\"') for `"'.
To use an odd number of double quotes as a key in an assignment, use the typeset builtin and an enclosing pair of double quotes; to refer to the value of that key, again use double quotes:
typeset -A aa typeset "aa[one\"two\"three\"quotes]"=QQQ print "$aa[one\"two\"three\"quotes]"
It is important to note that the quoting rules do not change when a parameter expansion with a subscript is nested inside another subscript expression. That is, it is not necessary to use additional backslashes within the inner subscript expression; they are removed only once, from the innermost subscript outwards. Parameters are also expanded from the innermost subscript first, as each expansion is encountered left to right in the outer expression.
A further complication arises from a way in which subscript parsing is not different from double quote parsing. As in true double-quoting, the sequences `\*', and `\@' remain as two characters when they appear in a subscript expression. To use a literal `*' or `@' as an associative array key, the `e' flag must be used:
typeset -A aa aa[(e)*]=star print $aa[(e)*]
A last detail must be considered when reverse subscripting is performed. Parameters appearing in the subscript expression are first expanded and then the complete expression is interpreted as a pattern. This has two effects: first, parameters behave as if GLOB_SUBST were on (and it cannot be turned off); second, backslashes are interpreted twice, once when parsing the array subscript and again when parsing the pattern. In a reverse subscript, it's necessary to use four backslashes to cause a single backslash to match literally in the pattern. For complex patterns, it is often easiest to assign the desired pattern to a parameter and then refer to that parameter in the subscript, because then the backslashes, brackets, parentheses, etc., are seen only when the complete expression is converted to a pattern. To match the value of a parameter literally in a reverse subscript, rather than as a pattern, use `${(q)name}' (see zshexpn(1)) to quote the expanded value.
Note that the `k' and `K' flags are reverse subscripting for an ordinary array, but are not reverse subscripting for an associative array! (For an associative array, the keys in the array itself are interpreted as patterns by those flags; the subscript is a plain string in that case.)
One final note, not directly related to subscripting: the numeric names of positional parameters (described below) are parsed specially, so for example `$2foo' is equivalent to `${2}foo'. Therefore, to use subscript syntax to extract a substring from a positional parameter, the expansion must be surrounded by braces; for example, `${2[3,5]}' evaluates to the third through fifth characters of the second positional parameter, but `$2[3,5]' is the entire second parameter concatenated with the filename generation pattern `[3,5]'.