bash-as-sh echo -n

bash-as-sh echo -n

有没有办法让 bash (版本 3.2.57(1),如果重要的话)在模拟 sh 的模式下实现内置-n选项echo

具体来说,我很好奇是否可以在某处设置一个选项,而不是echo -n在 M 个不同的脚本中寻找并重写 N 个调用,而这些选项多年来一直运行良好(也许只是运气不好)。显然 bash 的内置函数可以echo 实现-n,因为在完整的 bash 模式下,它确实可以实现。

[免责声明:是的,我知道这echo -n首先是不可移植的,但printf建议这样做。]


旁注:评论者指出这个版本的 bash 已经“17 岁了”。有人应该告诉 Apple 这件事——这是我在相当新的 Mac 上随 MacOS Ventura 13.0 附带的版本。

答案1

我能想到的最好的主意是用GNU coreutils 中的echo“真正的”echo可执行文件替换内置函数,如果你有 bash,几乎肯定会安装它:

echo() { "$(type -P echo)" "$@" ; }

它只是隐藏了内置的。

由于 GNU Coreutilecho.c确实不是很长,其中很大一部分是特殊情况处理,例如“我在 UNIX System V 上运行并且预计会有这样的行为吗?”、--help打印和类似的事情严格地如果需要,您可以考虑在您的 shell 脚本中包含一个小的 C 实现,echo并通过 POSIX 指定的方式将其放入(c99如果您知道自己已经实现了)。哎呀,这是一台 2000 年代的机器,所以您不妨假设您有 Perl 并在 Perl 中实现相同的功能。

答案2

正如所见为什么 printf 比 echo 更好?, 当同时启用该选项(例如作为 调用时)并且启用该选项(因为默认情况下在构建 bash 以便与 UNIX 兼容的系统上)时,bash不支持该-n选项(也不支持-e/ -E) 。posixshxpg_echo

因此,要获得 bash 的echo支持-n(和-e/-E及其组合,例如echo -enecho -e -n...),您需要禁用其中一个或两个选项。如果您希望sh除此之外仍然兼容 UNIX -n,则可能xpg_echo只需将其关闭:

shopt -u xpg_echo

例子:

$ bash -o posix -O xpg_echo -c 'echo -n a'
-n a
$ bash -o posix -O xpg_echo -c 'shopt -u xpg_echo; echo -n a'
a

bash 仍然大部分与 UNIX 兼容,除了-n未打印的内容。

$ bash -o posix -O xpg_echo -c 'set +o posix; echo -n a'
a

启用了该-n处理,但也启用了一些其他非 UNIX 合规性,因此它的行为更不像标准sh.

答案3

我的 Mac 上的外部设备/bin/echo确实支持-n,您可以使用以下命令禁用 Bash 内置功能enable -n

bash-3.2$ enable -n echo
bash-3.2$ type echo
echo is /bin/echo
bash-3.2$ echo -n foo |od -c
0000000    f   o   o
0000003

答案4

解决根本问题

如果您使用“升级 bash macOS”作为搜索词,Google 将返回大量结果。使用本地交换答案,并将 2 个答案合并为一个(根据您的旁注):

有关 GNU 许可证的常见问题:Tivoization

当人们分发包含 GPLv3 下的软件的用户产品时,第 6 节要求他们向您提供修改该软件所需的信息。用户产品是许可证中专门定义的术语;用户产品的示例包括便携式音乐播放器、数字录像机和家庭安全系统。

由于Apple的Darwin OS从10.5左右开始就已经闭源,提供升级的BASH将违反上述段落,因此Apple确实知道。有一种方法可以更新 BASH shell,甚至将其设为默认 shell:

通过 Homebrew 安装更新的 Bash

将以下内容粘贴到您的终端中:

  1. /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"作为一行。
  2. 问题brew install bash

这应该在 Homebrew 中安装 BASH 的更新版本,然后进行符号链接。用于which bash查找位置 要将其设置为默认位置:

  1. 编辑/etc/shells
  2. 将路径+二进制文件添加到文件末尾。
  3. 注销并重新登录以更新您的环境。
  4. 使用chsh命令“Change Shells”,提供新 BASH 版本的路径。这应该使新版本成为您的默认 shell。

来源

相关内容