[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Exporting functions does not expand aliases in subshells
From: |
Robert Elz |
Subject: |
Re: Exporting functions does not expand aliases in subshells |
Date: |
Thu, 11 Apr 2024 21:08:16 +0700 |
Date: Thu, 11 Apr 2024 11:05:43 +0200
From: Philipp Lengauer <p.lengauer@gmail.com>
Message-ID:
<CAFJdOf65G9XShQ7VKSu8yp2+QtzOBwZeq=RNUsM45n15NVpBWA@mail.gmail.com>
| When defining aliases and then exporting a function uses these aliases, the
| exported function body has the aliases expanded. This makes sense because
| we cannot be sure the same aliases exist in the child process where the
| exported function will eventually be used.
That's not the reason it happens though - it happens because aliases
(which are an obnoxious idea, rarely really work the way you'd like
them to - as here - and should be avoided completely) are expanded as
the input is read (they're a lexical construct) when one is detected
at the appropriate position.
ie: when you do:
alias echo='echo PREFIX'
echo hello world
what the lexical analyser hands to the parser is:
alias echo='echo PREFIX'
echo PREFIX hello world
But if you were to write
E=
$E echo hello world
then the alias wouldn't be expanded ("echo" is not in the command
word position when the lexical analyser runs, $E is - when later
run, $E vanishes (as E is empty) and the echo command is run, but
by then it is way too late for aliases to affect anything.
Aliases are stupid!
| However, when using subshells in
| the child process, the aliases are not expanded.
I think you'll find they are. Where they're not expanded is in
command substitutions (in bash anyway) - as (bash) doesn't parse
those until they're executed (well, to be strict, they're parsed
twice, once just to locate their end, and the results are discarded,
and then again when they're used). Since aliases aren't exported,
(which I hope never changes - or more importantly, that there is never
a way to allow aliases to be imported) when the shell parses the
command substitution (in the shell environment which has imported it)
the environment has no alias, so obviously it cannot work as you expected.
You'd see the same thing if your function was
foo() { eval "echo 'hello world'"; }
as again, the eval string is parsed only when it is executed (and
for eval, unlike the command substitution example, this is important)
and if you export the foo function, the "echo" being in a string
isn't expanded as an alias. Nor should it be. (It would be if you
ran this version in a shell which has an alias for echo defined.)
| This is unexpected behavior and potentially breaks the function.
Using aliases tends to break things. There's never a really good
(sane) reason to do so, just don't do that.
Instead of
alias echo='echo PREFIX'
just do
echo() { command echo PREFIX "$@"; }
(and export that if that's what you need).
kre