Re: declare XXX=$(false);echo $?
On Fri, 2 Dec 2022 at 20:28, Ulrich Windl wrote: > Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") > "Surprising" is subjective. There is no indication in the manual page that "declare" ignores the exit > code of commands being executed to set values. > Framing this as `declare` "ignoring" something indicates a possible misunderstanding of the separate phases of execution. Every command (with exactly three exceptions) sets its own exit status without regard for any previous value of $?, including any set by $(...) expansions used to create the command in question. If anything is weird, it's that simple (bare) assignments set $? to 0 UNLESS there's a command substitution providing a status. The other two exceptions are `return` and `exit`, which use the previous $? as the default if no parameter is supplied. Like every other command, including "declare", sets its exit status independently of what $? is before it runs. So it's somewhat of a mystery why anyone would expect "declare" to be any different. (Actually, it's no mystery: cargo-cult coding is the norm, as the majority of people writing shell scripts have not read all of "man bash" and have little idea of how the shell is actually supposed to work. So perhaps Bash needs an officially sanctioned "beginners' guide".) Found in the real code (intended to trigger a bug): > declare ERRORS=0 ARGS=$(getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- > "$@") > if [ $? -ne 0 ]; then > usage > fi > That is a well-known anti-pattern that should be avoided. Some working equivalents would be: ``` declare ARGS=$( getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- "$@" ) ERRORS=$? (( ERRORS == 0 )) || usage ``` or: ``` declare ARGS ERRORS=0 ARGS=$( getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- "$@" ) || usage ``` -Martin (PS: "Working" would be questionable, since putting `getopt` in a subshell prevents it from updating "$@"; and `test $? = 0` and its variants are pointless clutter.)
Re: declare XXX=$(false);echo $?
Chet Ramey writes: > On 12/2/22 5:28 AM, Ulrich Windl wrote: >> Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") >> There is no indication in the manual page that "declare" ignores the >exit code of commands being executed to set values. > > Why do you think it should? `declare' has a well-defined return status. There it is, end of "SIMPLE COMMAND EXPANSION": If there is a command name left after expansion, execution proceeds as described below. Otherwise, the command exits. If one of the expanâ sions contained a command substitution, the exit status of the command is the exit status of the last command substitution performed. If there were no command substitutions, the command exits with a status of zero. and: declare [-aAfFgiIlnrtux] [-p] [name[=value] ...] typeset [-aAfFgiIlnrtux] [-p] [name[=value] ...] [...] The return value is 0 unless an invalid option is encountered, an attempt is made to define a function using ``-f foo=bar'', an attempt is made to assign a value to a readonly variable, an attempt is made to asâ sign a value to an array variable without using the compound asâ signment syntax (see Arrays above), one of the names is not a valid shell variable name, an attempt is made to turn off readâ only status for a readonly variable, an attempt is made to turn off array status for an array variable, or an attempt is made to display a non-existent function with -f. If you input "XXX=$(false)", there isn't a command name, it's a sequence of assignments, and "the exit status of the command is the exit status of the last command substitution performed". But if you input "declare XXX=$(false)", you're executing the "declare" command, and the exit status doesn't depend on the command substitution. Dale
Re: declare XXX=$(false);echo $?
On 12/2/22 5:28 AM, Ulrich Windl wrote: Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") There is no indication in the manual page that "declare" ignores the exit code of commands being executed to set values. Why do you think it should? `declare' has a well-defined return status. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: declare XXX=$(false);echo $?
On Fri, Dec 02, 2022 at 11:28:50AM +0100, Ulrich Windl wrote: > Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") https://mywiki.wooledge.org/BashPitfalls#pf27
Re: declare XXX=$(false);echo $?
On Fri, 2 Dec 2022 at 21:29, Ulrich Windl wrote: > Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") > There is no indication in the manual page that "declare" ignores > the exit code of commands being executed to set values. The above is not surprising at all. 'declare' is a builtin command. It succeeded. $ help declare | tail -n 3 Exit Status: Returns success unless an invalid option is supplied or a variable assignment error occurs. 'man bash' explains this comprehensively. The return value is 0 unless an invalid option is encountered, an attempt is made to define a function using ``-f foo=bar'', an attempt is made to assign a value to a readonly variable, an attempt is made to as‐ sign a value to an array variable without using the compound as‐ signment syntax (see Arrays above), one of the names is not a valid shell variable name, an attempt is made to turn off read‐ only status for a readonly variable, an attempt is made to turn off array status for an array variable, or an attempt is made to display a non-existent function with -f. Also, $(false) probably does not produce the value of $XXX that you expect. Try running 'echo $(false)'.
declare XXX=$(false);echo $?
Surprisingly "declare XXX=$(false);echo $?" outputs "0" (not "1") There is no indication in the manual page that "declare" ignores the exit code of commands being executed to set values. Actually I's consider it to be a ASH bug, not a documentation bug. Found in the real code (intended to trigger a bug): declare ERRORS=0 ARGS=$(getopt -o "$S_OPTS" -l "$L_OPTS" -n "$0" -- "$@") if [ $? -ne 0 ]; then usage fi ++ getopt -o e:i:v -l exclude:,include:,verbose -n ./buggy.sh -- add -vv -iHCTL_DEFS -k SAPDA_DEFS -- -p ./buggy.sh: invalid option -- 'k' + declare ERRORS=0 'ARGS= -v -v -i '\''HCTL_DEFS'\'' -- '\''add'\'' '\''SAPDA_DEFS'\'' '\''-p'\''' + '[' 0 -ne 0 ']'