I am sorry I made a mistake in the first email. Bash printed foo= bar=v and all other shells printed foo=v bar=. It turns out I am using --posix to enable alias in bash, and that’s what makes the difference.
# file test shopt -s expand_aliases 2>/dev/null alias al=' ' alias foo=bar al for foo in v do echo foo=$foo bar=$bar done $ bash ./test foo=v bar= $ bash --posix ./test foo= bar=v 发件人: Chet Ramey<mailto:chet.ra...@case.edu> 发送时间: 2023年1月17日 3:41 收件人: anonymous4feedb...@outlook.com<mailto:anonymous4feedb...@outlook.com>; bug-bash@gnu.org<mailto:bug-bash@gnu.org> 抄送: chet.ra...@case.edu<mailto:chet.ra...@case.edu> 主题: Re: Possible bug in bash On 1/15/23 7:42 AM, anonymous4feedb...@outlook.com wrote: > For the follow script > alias al=' ' > alias foo=bar > al for foo in v > do echo foo=$foo bar=$bar > done > bash (version 5.1.16) prints foo=v bar=, while all other shells I tested > (dash, ksh, zsh, and yash) all prints foo= bar=v. That's strange. I get the same results you do for bash, but I tried the same shells you did and got the same results as bash (for different reasons, I suspect). $ cat x4 shopt -s expand_aliases 2>/dev/null alias al=' ' alias foo=bar al for foo in v do echo foo=$foo bar=$bar done $ ./bash ./x4 foo=v bar= $ dash ./x4 foo=v bar= $ ksh93 ./x4 foo=v bar= $ yash ./x4 foo=v bar= $ mksh ./x4 foo=v bar= $ zsh ./x4 foo=v bar= $ ./bash --version GNU bash, version 5.2.15(54)-maint (x86_64-apple-darwin21.6.0) Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. > Apparently bash substitutes foo for bar in line 3 because the previous alias > al ends with a space. But it is unintuitive that the word after for is > checked for alias. This is the opposite of what happens. In default mode, which you're probably using, bash checks `for' for aliases, and, finding none, stops checking. The other shells probably *don't* check whether `for' has an alias, because POSIX says reserved words can't be alias expanded ("However, reserved words in correct grammatical context shall not be candidates for alias substitution.") Either way, the `check the next word for alias expansion' flag gets turned off. > According to the posix standard, > If the value of the alias replacing the word ends in a <blank>, the shell > shall check the next command word for alias substitution; this process shall > continue until a word is found that is not a valid alias or an alias value > does not end in a <blank>. > But “command word” is not defined. It is ambiguous whether “for” in this > context is a command word, or whether tokens other than command word is > allowed between the first alias and the next command word. `Command word' refers to the previous paragraph: since alias expansion is attempted on "a resulting word that is identified to be the command name word of a simple command," the "next command word" is presumably the word following that one. > > The same is true for case > alias al=' ' > alias foo=bar > al case foo in foo) echo foo;; bar) echo bar;; esac Everybody prints `foo'. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRU c...@case.edu http://tiswww.cwru.edu/~chet/