在 zsh 中模拟 bash 破坏动态分配的文件描述符

在 zsh 中模拟 bash 破坏动态分配的文件描述符

我在脚本中使用动态分配的文件描述符,如本文所述:

zsh 和 POSIX 相当于 bash 的 `{var}>&1`

该脚本本身可以在 bash 和 zsh 之间移植,因此emulate -LR bash如果脚本检测到它正在 zsh 中运行,则会尽早执行。

不幸的是,这打破了exec {fd}>&...zsh 和 bash 已经支持相当长一段时间的功能。

为了说明这一点,该脚本成功了(在 bash 中也有效):

#!/usr/bin/env zsh

set -euo pipefail

for i in {1..10}; do
  exec {fd}> >( tee /dev/stderr | logger )

  echo "FD: ${fd}" >&"${fd}"
done

但这并不:

#!/usr/bin/env zsh

set -euo pipefail

emulate -LR bash

for i in {1..10}; do
  exec {fd}> >( tee /dev/stderr | logger )

  echo "FD: ${fd}" >&"${fd}"
done

command not found: {fd}

任何人都可以向我指出其幕后功能的完整列表emulate -R bash(也许我忽略了它,但我无法找到真正的手册页emulate)。或者更好的是,如果有人知道哪个特定选项导致此问题,那就太好了。

预先感谢您的任何帮助。

答案1

zsh没有bash仿真模式。如果您通过了bash(或以sor开头的任何内容b(对于伯恩)) 到emulate,它将使用sh仿真模式:

$ emulate bash -c emulate
sh

zsh的仿真模式有zsh(默认)、sh(最初主要是 SysV/Bourne sh,现在更多的是 POSIX shcshksh.

bash是一个主要兼容 POSIX 的 shell sh,但其扩展大部分来自 Korn shell,因此要zsh解释bash使用非 POSIX 扩展的代码,最好的选择是 ksh 模拟(您可能还想启用BASH_REMATCH预期的选项)为了bash兼容性)。

{fd}<功能实际上来自zsh.它是在 中同时实现的zshksh93并且bash是根据一位 zsh 开发人员在所有 3 个 shell 的维护者之间的讨论中的建议而实现的。

echo {fd}< /dev/nullPOSIX 需要输出{fd}(尽管这将在标准的未来版本中发生变化),因此在仿真zsh中禁用它sh。它不在ksh仿真中,因此您需要在这里使用它。

至于在哪个仿真(zsh、sh、ksh、csh)中启用哪个选项,请参阅手册中每个选项描述旁边的, <C>, <K>, ( )。<S><Z>info zsh 'Description of Options'

哪些选项影响该{fd}>...功能在手册 ( ) 中对该功能的描述中指定info zsh 'file descriptors, use with parameters'IGNORE_BRACES其描述 ( info zsh IGNORE_BRACES) 旁边有一个,表示它仅<S>在仿真中默认启用。sh

虽然zsh附带了手册页(其中一些),但手册页对于这么大的手册来说是相当不够的。我建议使用info超文本并具有可搜索索引和目录。要了解zshemulate内置内容,您可以运行info zsh emulate,或者从内部info zshI指数,然后输入emulate(可以使用制表符补全)。在某些系统上,您可能需要安装zsh-doc软件包或等效程序,因为默认情况下并不总是安装信息文档。

相关内容