View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0001976 | 1003.1(2024)/Issue8 | Shell and Utilities | public | 2026-03-13 21:10 | 2026-08-12 15:36 |
| Reporter | navi | Assigned To | |||
| Priority | normal | Severity | Editorial | Type | Enhancement Request |
| Status | New | Resolution | Open | ||
| Name | navi | ||||
| Organization | |||||
| User Reference | |||||
| Section | XCU: 2. Shell Command Language | ||||
| Page Number | -- | ||||
| Line Number | -- | ||||
| Interp Status | |||||
| Final Accepted Text | |||||
| Summary | 0001976: specify array variables and syntax | ||||
| Description | POSIX sh specifies one array per function, the argument array many sh implementations support having array variables past the argument array due to posix shell specifying a syntax for the argument array, sh implementations with array extensions naturally landed on similar and compatible syntax mksh, ksh93, bash, zsh, osh, yash, all support the following syntax: foo=(a b "c d" e) foo+=(f g) "${foo[@]}" # a b "c d" e f g "${foo[*]}" # "a b c d e f g" "${foo[expr]}" # indexed by expr, where expr is evaluated like $(( expr )) "${#foo[@]}" # 6, the lenght of foo additionally, mksh, ksh, and zsh, support declaring arrays as such: set -A name -- values notably ksh does not implement the name=(values) syntax, but has no other syntax that would conflict with it either ash and dash do not currently implement any sort of arrays, but also have no syntax that conflicts with the existing extensions | ||||
| Desired Action | rough first draft of changes: XBD 4.25: specify varname=(value) as assigning an array variable specify varname[expr]=value as assigning a entry in the array XCU: 2.5: specify array variables as containing an array of arbitrary byte sequences, except for null byte XCU: 2.6.2: specify ${parameter[@]} and ${parameter[*]} expansions matching 2.5.2 special parameters specify ${parameter[expr]} expansion, where expr is arithimetically expanded, then parameter is expanded matching 2.5.1 positional parameters | ||||
| Tags | No tags attached. | ||||
|
|
IMO, specifying arrays in POSIX sh is both impossible (see https://unix.stackexchange.com/questions/238080/test-for-array-support-by-shell/238129#238129 for details) and undesirable. Arrays would be yet another kludge added to a clunky shell design. Arrays/lists should have been the primary variable type in shells and several shells like rc and derivatives or fish have understood that. Unix had a chance to have a shell with clean list variable support with rc (from plan9 / Unix v10 in the late 80s; intended to be the successor of the Bourne shell then), but it's too late now. For sh, you'd want to at least disable implicit word splitting globbing upon unquoted parameter expansion (like with the set +o shwordsplit +o globsubst of the zsh implementation of sh) and certainly not go with the Korn design (as copied by bash). The fact that in all Bourne-like shell with arrays, indices are interpreted as arithmetic expressions complicates the parsing and tokenising significantly and is source of all sorts of bugs and vulnerabilities in particular if you want to allow array elements in any places that expect an lvalue. If you find yourself needing arrays in a sh script, you're probably using the wrong tool: consider switching to perl, ruby or other proper interpreted language, or a shell without so much of a baggage. |
|
|
I'm not sure I agree with that conclusion. The point of POSIX should not be to define a clean shell language. As you point out, it's too late for that and this is visible for more than just arrays. But shell scripts are not used for writing complex software. The reality of the situation is that (a) questions like the one you've linked to occur because people rely on arrays in practice, (b) support for arrays exists in numerous shells and having a common standard is more desirable than each new shell diverging in some new way, and (c) scripts currently need to bake kludges into their scripts like the ones you suggest in your answer you've linked to. I don't think "use another language" is the appropriate answer here but rather that the goal of POSIX should be to provide a uniform way to use the features people rely so that scripts can at least be written in a portable manner. |
|
|
since more words were asked for, this is my best attempt at a mostly complete wording, though i could have missed a few details i don't think i can edit the `desired action` field, so i'm adding the new wording here, and feedback appreciated. the += operator was left out, it could be added at a later time while also being specified for strings ---- XCU: ----------------------------- 2.5: Parameters and Variables ----------------------------- on page 2478, line 80337, change: A parameter is set if it has one or more assigned values -------------------------- 2.6.2: Parameter Expansion -------------------------- on page 2487, line 80692, change: ${#parameter} ${#parameter[word]} String Length. The shortest decimal representation of the length in characters of the first value of parameter, starting from zero, or the value denominated by word if word evaluates to one or more digits, shall be substituted. on page 2487, after line 80695, add: ${#parameter[@]} or ${#parameter[*]} Array Length. The decimal representation of the number of set values of parameter shall be substituted. If parameter is unset and set -u is in effect, the expansion shall fail." on page 2487, after line 80716, add: ${parameter[@]} Expands to the values of parameter, starting from zero, initially producing one field for each value that is set. When the expansion occurs in a context where field splitting will be performed, any empty fields may be discarded and each of the non-empty fields shall be further split as described in Section 2.6.5. When the expansion occurs within double-quotes, the behavior is unspecified unless one of the following is true: • Field splitting as described in Section 2.6.5 would be performed if the expansion were not within double-quotes (regardless of whether field splitting would have any effect; for example, if IFS is null). • The double-quotes are within the word of a ${parameter :−word} or a ${parameter :+word} expansion (with or without the <colon>; see Section 2.6.2) which would have been subject to field splitting if parameter had been expanded instead of word. If one of these conditions is true, the initial fields shall be retained as separate fields, except that if the parameter being expanded was embedded within a word, the first field shall be joined with the beginning part of the original word and the last field shall be joined with the end part of the original word. In all other contexts the results of the expansion are unspecified. If parameter has no values, the expansion shall generate zero fields, even when it is within double-quotes; however, if the expansion is embedded within a word which contains one or more other parts that expand to a quoted null string, these null string(s) shall still produce an empty field, except that if the other parts are all within the same double-quotes as the expression, it is unspecified whether the result is zero fields or one empty field. ${parameter[*]} Expands to the values of parameter, starting from zero, initially producing one field for each positional parameter that is set. When the expansion occurs in a context where field splitting will be performed, any empty fields may be discarded and each of the non-empty fields shall be further split as described in Section 2.6.5. When the expansion occurs in a context where field splitting will not be performed, the initial fields shall be joined to form a single field with the value of each parameter separated by the first character of the IFS variable if IFS contains at least one character, or separated by a <space> if IFS is unset, or with no separation if IFS is set to a null string ${parameter[word]} If word evaluates to one or more digits, the value of parameter denoted by word shall be substituted. Otherwise, the first value of parameter, starting from zero, shall be substituted. ----------------------------- 2.9.1.2: Variable Assignments ----------------------------- on page 2501, after line 81278, add: If value starts with an unquoted open parenthesis and no command results, all characters following the open parenthesis to the matching closing parenthesis shall be split into assignments. If any assignment has the form [word]=value, the behaviour is undefined. Each assignment shall be expanded as a word (see Section 2.6.2) and Field splitting (see Section 2.6.5) shall be performed on any fields generated by the expansion, each resulting field shall be assigned to as values to the variable, in order, starting from zero. Then the variable shall be given the array attribute, and it's export attribute shall be removed. If value starts with an unquoted open parenthesis and a command name results, the behaviour is undefined. ------------------------------------------- 2.10.2.7: Assignment preceding command name ------------------------------------------- on page 2514, line 81790, change: If all the characters in the TOKEN preceding the first such <equals-sign> form a valid name (see XBD Section 3.216, on page 63), or a valid name, followed by open bracket, word, and close bracket, the token ASSIGNMENT_WORD shall be returned. on page 2514, line 81797, change: If a returned ASSIGNMENT_WORD token begins with a valid name and is not followed by open-bracket, word, close-bracket, assignment of the value after the first <equal-sign> to the first value of name, starting from zero, shall occur as specified in Section 2.9.1. on page 2514, after line 82800, add: If a returned ASSIGNMENT_WORD token begin with a valid name followed by open-bracket, word, close-bracket, and if word evaluates to one or more digits, the assignment of value to the parameter value denoted by word shall occur as specified in Section 2.9.1, otherwise if word does not evaluate to one or more digits, the assignment of the first value of parameter, starting from zero, shall occur. Then the variable shall be set as an array, and it's export attribute shall be unset. If a returned ASSIGNMENT_WORD token begin with a valid name followed by open-bracket, word, close-bracket, and value begins with an unquoted open-parenthesis, the behaviour is undefined. -------------------------------- 2.15: Special Built-In Utilities -------------------------------- on page 2538, after line 82777, add: If the variable corresponding to a specified name has the array attribute, it shall not be given the export attribute. alternatively: If the variable corresponding to a specified name has the array attribute, the behaviour is undefined. on page 2571, after line 83910, add: If name has the form `name[word]`, if word evaluates to one or more digits, the value of `name` denominated by word shall be unset, otherwise it's first value, starting from zero, shall be unset. ----- ----- a few notes: for array length expansions: --- since zsh and pdksh derivatives counts gaps in Array Length expansions, it may be necessary to also include: "If there are unset values in parameter between set values, the behaviour is undefined." although zsh does already differ from posix in numerous points, it could also emulate this behaviour in sh mode. i am unsure if pdksh or derivatives could do so --- yash has quite a few changes that differ from all other shells, but as they do not make arrays available when ran as `sh`, it shouldn't be a problem to implement a similar syntax to the other shells when in sh mode --- zsh and ksh derivatives allow `set -A array [values...]` to set a variable as an array, in addition to `array=()` bash does not support set -A, but also has no conflicting -A flag in set, so specifying both array=(), which is the most commonly used form, and set -A, could be considered. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-03-13 21:10 | navi | New Issue | |
| 2026-04-24 07:17 | stephane | Note Added: 0007423 | |
| 2026-04-25 06:04 | Love4Boobies | Note Added: 0007424 | |
| 2026-08-12 15:36 | navi | Note Added: 0007485 |