在Bash中,env命令的作用是什么?

13

我在使用 Bash(在 Cygwin 下)时遇到了这种行为:

$ printf '\u00d5'
\u00d5
$ env printf '\u00d5' # This results in the behavior I want
Õ

在终端中使用UTF-8或ISO-8859-1编码并不重要。

我的问题是: env具体是做什么的?为什么我在这种特定情况下需要它?


2
有趣的发现。在Linux上也发生了类似的事情。对于第一个情况,我只得到了 ?(未知Unicode字符),但是对于第二个情况,我得到了相同的结果。 - Aaron Digulla
1个回答

17

env 不是 bash 的一部分,而是一个独立的可执行文件,用于在运行程序之前设置或清除环境变量。在您的特定情况下,它正在运行二进制文件 printf 而不是 shell 内置函数。您可以通过使用绝对路径来实现相同的结果:

/usr/bin/printf '\u00d5'
最不侵入性的方法可能是重新定义printf函数,让Bash处理剩下的部分。引用一个包含以下内容的文件:
```bash printf () { if [[ $1 = '-v' ]]; then # let the original printf handle it command printf "$@" else # redirect to stderr command printf "$@" >&2 fi } ```
function printf()
{
  $(which printf) "$@"
}
或者作为一行代码function printf() { $(which printf) "$@"; }。当然,您可以将$(which printf)替换为/usr/bin/printf...
然后只需像您习惯的那样使用printf。您的脚本保持不变,甚至可以引入条件来仅在某些Bash版本上定义函数。
据我所知,您还可以省略function,但我发现它可以提高可读性。
[编辑:关键字functionbash扩展;printf () { ...; }是POSIX语法。如果您使用function关键字,则函数名后面的括号是可选的。]
常见的做法是,在旨在具有可移植性的脚本的哈希-棒行中也使用env。原因是env几乎总是位于/usr/bin/env,而bash并不总是位于/bin/bash,正如许多哈希-棒行所暗示的那样。例如:
#!/usr/bin/env bash

同样适用于其他程序/解释器:

#!/usr/bin/env python

1
+1 我正准备在 Linux 系统上确认,然后发表同样的观点。 - chepner
3
我想知道为什么bash内置命令不能正确处理\u。根据帮助页面(help printf),它应该像二进制文件一样工作,而二进制文件的手册页(man printf)上写着"\uHHHH 4位16进制数表示的Unicode(ISO/IEC 10646)字符"。 - Aaron Digulla
@MichaelKrelin-hacker:我添加了一个bash内部的替代方式;) … commandbuiltin的相反,两者都可以用于“前缀”后续命令,并导致执行命令的外部或bash内部版本。 - 0xC0000022L
现在我迷失了。@0xC0000022L - 它不起作用。而且"printf" '\u00d5'也不行。 - Michael Krelin - hacker
1
command 只抑制了 shell 函数的查找,但它仍然优先选择内置命令而不是外部程序。 - chepner
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接