With dash, one can defined an alias with a backslash: $ alias '\mv=echo ab' $ alias \mv='echo ab' but it can't be used: $ \mv mv: missing file operand Try 'mv --help' for more information. So, it would be better to return an error like with bash and ksh93.
Indeed; escaping of any kind (quoting or backslash) disables alias expansion. What's even more fun is that if you do alias "a'b=c" "ls&id=cd" then alias will give you ls&id='cd' a'b='c' which is even better since it'll run code when evaled back. I posted a patch to dash@ (archived at forwarded-to) that fixes this by refusing characters that must be quoted in the name bit of the alias, so the invocation above will fail with alias: a'b: invalid name alias: ls&id: invalid name and commit no aliases. наб
Rejected by upstream, citing minimalness. A related fix for eval "alias $(alias 'a|b|c=d'; alias)" executing code was accepted (well "will look into it"ed, where "it" is my complete patch? idk), tho. This makes dash, as you note, incompatible with ksh93 and bash, but compatible with zsh in this regard. Seeing as this is an extension to POSIX (which requires that the name matches [a-zA-Z0-9_!%,@]+), both approaches are valid. Tentatively tagging as wontfix, maybe Andrej will want to pull that in as a patch, but upstream has spoken for the time being. наб
No, it is still incompatible with zsh, where one can use the alias:
zira% alias '\mv=echo ab'
zira% alias
'\mv'='echo ab'
run-help=man
which-command=whence
zira% \mv
ab
zira%
But perhaps if an alias with a backslash is accepted like in zsh,
then the fact that it is not used by dash is a bug. This doesn't
match the dash man page:
Aliases
An alias is a name and corresponding value set using the alias(1)
builtin command. Whenever a reserved word may occur (see above),
and after checking for reserved words, the shell checks the word
to see if it matches an alias. If it does, it replaces it in the
input stream with its value. [...]
and about the backslash:
Backslash
A backslash preserves the literal meaning of the following character,
with the exception of ⟨newline⟩. A backslash preceding a ⟨newline⟩
is treated as a line continuation.
But backslash handling is normally done *after* checking for aliases.
This typically allows one to disable an alias by using a backslash:
$ alias foo="echo ab"
$ foo
ab
$ \foo
dash: 3: foo: not found
$ f\oo
dash: 4: foo: not found
Hi! I meant the compatibility insofar as the alias name domain (and, roughly, the output when the name needs quoting). I didn't even try the expansion behaviours, because none of them should expand, and zsh is wrong to do this (quoting my patch from forwarded-to): + * POSIX Issue 7, XCU, 2.3.1 Alias Substitution: + * the command name word of a simple command shall be examined + * to determine whether it is an unquoted, valid alias name + * POSIX Issue 7, XCU, 2.2 Quoting: + * The various quoting mechanisms are the escape character, + * single-quotes, and double-quotes. As in one /can/ accept anything in the name (XBD, 3.10 Alias Name), but /must not/ expand aliases when the word is in any way quoted. Yeah, you're right here; dash conforms to the standard and doesn't alias-expand quoted command names, sorry for the confusion. (Also, the command name in your last prompt is "mv", so it's doubly weird that zsh allows it to match "\mv". In sh and ksh compatibility mode, which zsh apparently has, zsh does behave like dash/POSIX (allows anything in the name, doesn't expand aliases when quoted)). Best, наб
I would say that "\mv" is a quoted version of "mv", but an unquoted version of "\mv". I suspect that the POSIX text is based on the fact than normally, alias names cannot contain quote mechanisms. Otherwise it is rather ambiguous. Note also that https://pubs.opengroup.org/onlinepubs/9699919799/utilities/alias.html says: "An alias definition provides a string value that shall replace a command name when it is encountered", with no restrictions on words with quoting mechanism. No, alias substitution is done before quoting mechanisms are involved. Otherwise one would get an error in the following: $ alias 'foo=\echo ab' $ alias foo='\echo ab' $ foo ab However, emulation is not perfect. For instance: zira% emulate ksh zira% alias '\mv=echo ab' zira% ksh93 $ alias '\mv=echo ab' ksh93: alias: \mv=echo ab: invalid alias name I also suspect that if aliases with backslashes have been defined before zsh is put in sh/ksh compatibility mode, like that: zira% alias '\mv=echo ab' zira% emulate sh zira% alias '\mv'='echo ab' run-help=man which-command=whence then such aliases must be ignored in sh/ksh compatibility mode to avoid some surprises. This can explains the zsh behavior in alias substitution. However, in sh/ksh compatibility mode, I would rather expect alias '\mv=echo ab' to give an error, as the alias name is invalid in this context. BTW, the zsh extension makes sense if one want to be able to alias some forms of commands with special characters. For instance: zira% alias '\\foo=echo ab' zira% \\foo ab zira% ""\\foo zsh: command not found: \foo
Hi!
Well, when turning tokens into words, quotes are removed (XCU, 2.6), so.
Not really. The only bit affected is that XCU, alias, STDOUT only
requires that the value be quoted for reinput to the shell, and not the
name; naturally if you accept more than the minimum
(XBD, 3.10 Alias Name: [a-zA-Z!^,@]+),
then you should quote the name to preserve this property as well.
Yes, and it includes a link to the shell tokenisation rules,
which are actually normative w.r.t. when alias substitution happens:
After a token has been categorized as type TOKEN (see Section 2.10.1), including (recursively)
any token resulting from an alias substitution, the TOKEN shall be subject to alias substitution
if:
* the TOKEN does not contain any quoting characters,
* the TOKEN is a valid alias name (see XBD Section 3.10),
* an alias with that name is in effect,
* the TOKEN did not either fully or, optionally, partially result from an alias substitution of
the same alias name at any earlier recursion level, and
* the TOKEN could be parsed as the command name word of a simple command (see
Section 2.10), based on this TOKEN and the tokens (if any) that preceded it, but ignoring
whether any subsequent characters would allow that,
(Issue 8 Draft 2.1, cf. https://www.austingroupbugs.net/view.php?id=953;
Issue 7 says the same thing about the quoting bits but less eloquently.)
No? Again, XCU, 2.3.1 Alias Substitution:
When a TOKEN is subject to alias substitution, the value of the alias shall be processed as if it
had been read from the input instead of the TOKEN, with token recognition (see Section 2.3)
resuming at the start of the alias value. When the end of the alias value is reached, the shell may
behave as if an additional <space> character had been read from the input after the TOKEN that
was replaced. If it does not add this <space>, it is unspecified whether the current token is
delimited before token recognition is applied to the character (if any) that followed the TOKEN
in the input.
"foo\n" is read, partially tokenised as as [<foo>, ...], this satisfies
the conditions above, tokenisation restarts on "\\echo ab\n",
this yields [<\echo>, ...], this contains a quote, so tokenisation
continues for [<\echo>, <ab>]; <\echo> isn't a reserved token, so
XCU 2.10.2 pt. 7a doesn't apply so pt. 1 sentence 2 applies and
word expansion occurs, yielding a simple_command consisting of
cmd_name=(echo) cmd_suffix=(ab)
(i ran out of markup for WORDs, parens must do).
"echo" is executed with single parameter "ab".
(Roughly; the syntax is mind-numbing, and there's so many steps that do
nothing here. You get the point.)
Well, I wouldn't say "ignored". The Zsh Language just applies
a different set of rules to alias expansion (effectively, it provides
aliases for TOKENs instead of WORDs; this is weird and confusing,
since you /never/ observe TOKENs directly like this and you /execute/
WORDs; frankly, the decision to not do quote removal in this context is
/baffling/, but, y'know. zsh.). Under sh emulation it applies the correct
rules. In both languages all characters are valid parts of an alias.
Why? Again, XBD, 3.10 Alias Name:
Implementations may allow other characters within alias names as an extension.
You directly observe that a backslash is a valid part of an alias name
because alias didn't exit >0. It's just fundamentally impossible for it
to ever actually get substituted. This matches dash.
Many characters aren't valid parts of the alias name under ksh and bash
(and mksh), even those that would be fine to substitute (under bash
that's the slash). That's fine, too.
Best,
наб
Control: clone -1 -2 Control: retitle -2 dash: accepts anything as an alias name and doesn't quote it, then eval $(alias) will run alias as code Control: tags -2 - wontfix Control: tags -2 + fixed-upstream This new-found bug (-2 if i got my headers right) has been fixed in: https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=4ec545e8dc98a3f461cf56bed03adafa81c64aec by just quoting the alias names in addition to the values. The original bug remains upstream wontfix. наб