[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: executes statement after "exit"
From: |
Chet Ramey |
Subject: |
Re: executes statement after "exit" |
Date: |
Sat, 16 Apr 2022 12:09:21 -0400 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.8.0 |
On 4/15/22 2:34 PM, Frank Heckenbach wrote:
#!/bin/bash
: $((08 + 0)); exit
echo "Should not get here."
It never executes `exit'.
The explanation in
https://lists.gnu.org/archive/html/bug-bash/2022-04/msg00010.html applies here.
The arithmetic syntax error (invalid octal constant) results in a word
expansion error (the $((...)) ), which causes the shell to abort execution
of the current command (the command list)
Current command means command list?
No, of course not. It means the shell command currently being executed. In
this case, that's a command list.
Let's go through it step by step. Bash always reads at least one line from
the input source, and parses all the commands on that line before executing
any of them. So in this case, we have the line
: $((08 + 0)); exit
which is parsed into a command list (a compound command) containing two
simple commands. Bash executes the command list, so the list is the current
command.
The top level in this scenario is the point in the input source where bash
has stopped reading because it has read and parsed a complete command and
can execute it -- the next character it will read at the top level is the
`e' in `echo'.
So bash attempts to execute the first simple command in the list, and
begins by performing word expansion on the arguments to `:'. It encounters
an expansion error, abandons execution of the command list, and jumps to
the top level to continue execution.
This is roughly equivalent to what happens when the shell is interactive.
It returns to its top-level parsing loop, prints a new prompt, and reads
and executes a new command.
So if "current command" is the command list, in
sleep 3; : <(echo foo >&2)
shouldn't it start the "echo" before the "sleep" (in order to pass
its stdout as a filename to the command list)?
No. That's not how the grammar works.
and jump back to the top level
to continue execution with the next command (echo).
Let't see. This is a command list, so according to your explanation,
due to the expansion error, neither the "exit" nor the "echo" is
run:
: $((08 + 0)); exit; echo "Should not get here."
Alright. Now, in "3.2.4 Lists of Commands" it says:
"A sequence of one or more newlines may appear in a list instead of a semicolon to
delimit commands."
So let's do this for the latter semicolon, resulting in:
: $((08 + 0)); exit
echo "Should not get here."
According to the above, this should still be one command list, so
the "echo" shouldn't run either, but it does.
No, because the shell always reads lines from the input and parses them.
It only reads more than one line from the input if it needs it to parse
some compound command. A simple example is
{
: $((08 + 0)); exit
echo "Should not get here."
}
where the shell will read both lines and parse them as a single list
because it needs to read the final close brace to complete the compound
command.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU chet@case.edu http://tiswww.cwru.edu/~chet/