2019-01-10 04:00:37 +0700, Robert Elz: [...] > Nor can we tell the shells not to expand words that would be > keywords when used elsewhere as currently users have the > ability to do that, and we cannot break existing conforming > applications. [...]
It seems there's been a misunderstanding. I'm not proposing to break shell implementations. My proposed change would on the contrary give more freedom to implementations while giving slightly less freedom to applications (in areas where nobody cares anyway) and also align with existing implementations (including zsh, bash when not in POSIX mode, and AT&T ksh). I've just realised I had already made that point in 2016 at http://austingroupbugs.net/view.php?id=953#c3195 To rephrase it: Currently and with the currently proposed change, the spec more or less tells us, the application writers: > You can pick whatever name you want for your alias provided > it's a [a-zA-Z0-9_!%@,]* name (and unspecified if not) > > If you pick a name that happens to be the name of any of the > shell reserved words (if, do, in, !, while...), that alias > will be expanded except in the situations where that name is > recognised as a reserved word. What I'm saying is that it would be more useful to make it: > You can pick whatever name you want for your alias provided > it's a [a-zA-Z0-9_!%@,]+ name and is not the name of a shell > reserved word (and unspecified if not) (also note the change from * to + above) And leave off the part about expansion or not of aliases for reserved words since one can't use a reserved word as an alias. That allows shells to do the more sensible thing of allowing aliasing reserved words like bash or zsh do (when not in sh mode) or ksh (for "select" only, not a concern here as portable applications can't use "select", aliases or not, except quoted) The only applications that that proposed change would break would be the hypothetical ones that would do things like: alias for=pour alias do=faire alias to_french='echo ' for word in for do; do eval "to_french $word" done (which already doesn't work in bash except in posix mode nor in zsh in posix mode or not). I'm not aware that anybody uses aliases that way. The trailing blank thing is more about "alias env='env '" when you want your aliases (but here aliases to commands not to random French words) to be expanded after "env". In any case, by no longer allowing pipelines, redirections, multiple commands, keywords, comments in alias values, empty or blank aliases, that proposed change breaks many applications, especially scripts. The ones that are least likely to be broken are the interactive usage ones like "alias ll='ls -l'" or "alias sudo='sudo '", but no one cares about POSIX compliance interactively. For instance, among my posts on unix.stackexchange.com, at a quick glance, these would have alias usages that would become non-conformant: https://unix.stackexchange.com/a/63868 https://unix.stackexchange.com/a/65113 https://unix.stackexchange.com/a/86785 https://unix.stackexchange.com/a/146147 https://unix.stackexchange.com/a/174681 https://unix.stackexchange.com/a/253505 https://unix.stackexchange.com/a/323132 https://unix.stackexchange.com/a/367112 https://unix.stackexchange.com/a/372484 https://unix.stackexchange.com/a/375157 https://unix.stackexchange.com/a/388257 https://unix.stackexchange.com/a/388697 https://unix.stackexchange.com/a/390285 https://unix.stackexchange.com/a/462760 https://unix.stackexchange.com/a/469773 https://unix.stackexchange.com/a/485501 And most usages of "alias" by modernish (https://github.com/modernish/modernish): ~/git/modernish$ grep -Pr '^\s*alias\s' . ./bin/modernish: alias readonly='typeset -rg' ;; ./bin/modernish:alias test=test 2>|/dev/null || _Msh_have FTL_NOALIAS 'No support for aliases at all.' ./bin/modernish: alias _Msh_testFn=: ./bin/modernish: alias local=typeset ./bin/modernish:alias not='! ' # note: final space = continue to expand aliases ./bin/modernish:alias so='{ let "$?==0"; }' # we'll add 'let' to shells without it ./bin/modernish:alias forever='while :;' ./bin/modernish: alias die='_Msh_doExit 128' ./bin/modernish:alias exit=_Msh_doExit ./bin/modernish: alias export=_Msh_issetExHandleExport ./bin/modernish:alias shellquoteparams='{ '\ ./bin/modernish: alias source='_Msh_doSource "$#" "$@"' ./bin/modernish: alias let='let --' ./bin/modernish: alias readonly='typeset -r"$([[ -o posixbuiltins ]] && builtin echo g)"' ./libexec/modernish/var/local.mm:alias LOCAL="{ ${_Msh_sL_ksh93}unset -v _Msh_sL; { _Msh_sL_LOCAL ${_Msh_sL_LINENO}" ./libexec/modernish/var/local.mm:alias BEGIN="}; isset _Msh_sL && _Msh_sL_temp() { eval \"\${_Msh_PPs+unset -v _Msh_PPs; set -- \${_Msh_PPs}}\"; " ./libexec/modernish/var/local.mm:alias END="} || die 'LOCAL: init lost'; _Msh_sL_temp \"\$@\"; _Msh_sL_END \"\$?\" ${_Msh_sL_LINENO}; }" ./libexec/modernish/var/loop.mm:alias LOOP='{ { { _Msh_loop' ./libexec/modernish/var/loop.mm:alias DO='}; _Msh_loop_c && '\ ./libexec/modernish/var/loop.mm: alias DONE='} 8<&-; done; } 8</dev/null 8<&-; _Msh_loop_setE; }' ./libexec/modernish/var/loop.mm: alias DONE='} 8<&-; done; } 8<&-; _Msh_loop_setE; }' ./libexec/modernish/var/stack/trap.mm:alias trap='_Msh_POSIXtrap' ./libexec/modernish/var/stack/trap.mm: alias trap='_Msh_printSysTrap' ./libexec/modernish/var/stack/trap.mm: alias trap='_Msh_POSIXtrap' ./libexec/modernish/var/stack/trap.mm: alias trap='_Msh_printSysTrap' ./libexec/modernish/var/stack/trap.mm: alias trap='_Msh_POSIXtrap' ./libexec/modernish/cap/BUG_LNNOALIAS.t:alias _Msh_BUG_LNNOALIAS_testAlias='_Msh_test=$LINENO' ./libexec/modernish/tests/run.sh:alias TEST='{ testFn() {' ./libexec/modernish/tests/run.sh:alias ENDT='}; doTest; }' ./libexec/modernish/tests/util.t: alias _util_test8="${CCn}x=\$LINENO${CCn}y=\$LINENO${CCn}z=\$LINENO${CCn}" It even breaks ksh93's builtin alias for "times": $ ksh -c 'alias times' times='{ { time;} 2>&1;}' In comparison, my proposed change is a lot less likely to break an application. Ironically, ksh93 has a builtin alias for "command" as well: $ ksh -c 'alias command' command='command ' When you do "command times" (which you may want to do as "times" is meant to be a "special builtin" per POSIX): $ ksh -c 'command times' ksh: syntax error at line 1: `{' unexpected -- Stephane