envsubst:在 Mac OS X 10.8 上找不到命令

问题描述 投票:0回答:6

当我尝试运行包含 envsubst 命令的脚本时,出现此错误。在网上看,这似乎是一个标准的 bash 命令,所以我不确定要安装什么才能让它工作。

bash shell terminal sh command-line-interface
6个回答
288
投票
brew install gettext
brew link --force gettext 

这将在 OS X 上启用 envsubst,并强制其正确链接。它需要安装自制程序。


158
投票

编辑:@cobberboy 的答案更正确。给他点赞。

brew install gettext
brew link --force gettext 

以下是我的旧答案:

envsubst
包含在
gettext
包装中。

因此,您可以使用标准构建工具(例如

make
)或使用
homebrew
自行编译它。

不过,在MacOS中安装

gettext
时似乎没有什么问题。 详细信息请参阅以下网址:如何在 MacOS X 上安装 gettext


24
投票

为了消除潜在的混乱:

  • envsubst
    是一个 external 可执行文件,因此 不是 Bash 的一部分;外部可执行文件是平台相关的,无论是可用的还是它们的特定行为和它们支持的特定选项(尽管希望有一个基于 POSIX 规范的通用子集)
  • 直接内置于
    bash
    中的命令称为 builtins,并且只有 它们 才能出现在 所有 平台
    上。

测试给定命令是否是内置命令,请使用:[1]

type <cmdName>

在本例中,在 macOS 14 (Sonoma) 上运行

type envsubst
返回
-bash: type: envsubst: not found
,从中您可以推断:

  • envsubst
    不是内置的
  • envsubst
    不在您系统的
    $PATH
    中(因此可能不存在于您的系统中)

(相比之下,在 Ubuntu 12.04 系统等上运行相同的 on 命令会返回

envsubst is hashed (/usr/bin/envsubst)
,这会告诉您该实用程序是否存在以及它位于何处。)


envsubst
的临时替代方案是使用
eval
,尽管通常需要注意:仅在您控制或信任其内容的字符串上使用
eval

假设

sample.txt
文件包含带有未展开的变量引用的文本;例如:

cat > sample.txt <<'EOF'
Honey, I'm $USER
and I'm $HOME.
EOF

相当于:

envsubst < sample.txt

是:

eval "echo \"$(sed 's/"/\\"/g' sample.txt)\""

但是,有一个关键区别

  • envsubst
    扩展仅环境变量引用
  • eval
    将扩展 shell 变量引用 too - 以及 嵌入式 命令替换,这就是使用
    eval
    带来 安全问题的原因。

[1] 如果给定命令 内置命令,则会打印一条消息,例如

<command> is a shell builtin
。要以以编程方式测试此条件,请使用类似
type <command> 2>/dev/null | grep -q builtin && echo "IS A BUILTIN"

的内容

4
投票

我现在在需要 envsubst 的 bash 脚本中使用它:

if ! which envsubst > /dev/null 2>&1; then
    envsubst() {
        while read line; do
            line=$( echo $line | sed 's/"/\\"/g' )
            eval echo $line
        done
    }
fi

您可以将它用作 envsubst 命令 - 当然它的功能不完整或其他:

envsubst <<<'Honey, I am $HOME.'
envsubst < input > output 2> corrupt

3
投票

如果您不想安装 homebrew 和 gettext,单行 perl 可执行文件就可以了:

#!/usr/bin/perl -p
$_ =~ s/\Q${$1||$2}/$ENV{$1?$2:$4}/ while $_ =~ /(\$\{([^}]+)})|(\$(\w+))/g;

3
投票

如果你不想安装 homebrew 和 gettext,并且 无法搞懂 Perl ,一个简单的 Python 脚本也能做到这一点:

envsubst() {
  python -c 'import os,sys;[sys.stdout.write(os.path.expandvars(l)) for l in sys.stdin]'
}

eval
解决方案相比,它的优势在于它仅处理变量替换,不会像
eval
那样执行任意脚本。

$ cat > sample.txt <<'EOF'
Honey, I'm $USER
and I'm $HOME.
Danger: $( echo 'eval can do evil here, but python expandvars rocks' )
EOF

$ envsubst < sample.txt

Honey, I'm mattmc3
and I'm /Users/mattmc3.
Danger: $( echo 'eval can do evil here, but python expandvars rocks' )
© www.soinside.com 2019 - 2024. All rights reserved.