shell调用的程序会继承shell变量吗?

shell调用的程序会继承shell变量吗?

如果我有这个 shell 脚本

str="A tremor in the Force.
The last time I felt it was in the presence of my old master."

cat <<< "$str"

我的理解是该命令

cat <<< "$str"

告诉 shell 调用程序/bin/cat并向其传递参数$str- 其中双引号$str确保 shell 将不改变地传递参数。因此,如果cat程序获得的$str变量未更改 - 那么它必须知道变量的值?我的问题是,shell 是否会将其环境中声明的变量传递给它调用的其他系统程序?

答案1

shell 是否会将其环境中声明的变量传递给它调用的其他系统程序?

是的,但不是在 的情况下cat <<< "$str"

在类 Unix 操作系统中,大多数新程序都是由于execve()系统的以下原因而执行的:

int execve(const char *filename, char *const argv[], char *const envp[]);

shell 用于execv执行程序,默认情况下,shell 会在 中传递所有环境变量envp,类似于在 中传递命令行参数的方式argv。从概念上讲,envp是一个数组字符串,每个字符串的格式为NAME=value

man 2 execve非常清楚地解释了整个过程,并包括工作示例代码。

在 的情况下cat <<<"$str",shell 向catoncat的标准输入提供“$str”,因此cat永远不会看到名为 的变量str,除非它之前由 shell 导出(例如通过调用)export str,但cat无法知道这两个变量是有关的。

<<<是一个“Here String”和一个 shell 扩展。从bash手册页:

该单词会经历大括号扩展、波形符扩展、参数和变量扩展、命令替换、算术扩展和引号删除。不执行路径名扩展和分词。结果作为单个字符串提供给标准输入上的命令。

Here String 与传统的习惯用法类似:

echo "$str" | cat

我推荐的。事实上,两者都会在标准输入末尾添加换行符。我相信这两种方法是相同的,只要echo不以任何方式修改输出(它可以取决于字符串的内容,因此更安全的版本是printf '%s' "$str"而不是echo)。

在您的情况下,我会使用它,printf '%s' "$str" | cat因为它是最便携、通用且易于理解的,而无需仅使用众多 shell 之一锁定脚本执行。如果您使用 POSIXsh手册页作为您的 shell 脚本文档,那么您需要掌握的材料就会减少,并且您学到的材料适用于所有 Bourne shell 衍生产品。

答案2

shell 调用的程序不会继承 shell 变量。它们仅继承环境变量。如果您编写export str(或以一些不太常见的方式),则变量会被放置在环境中,而不是仅分配给它。

cat无论如何都不会关心环境变量。

该命令cat <<< "$str"不会将任何参数传递给cat.它cat不带任何参数进行调用,但使用连接到管道的标准输入,shell 在该管道上写入变量的值str和换行符。该cat进程没有看到$str,它看到了A tremor … my old master(最后一个换行符)。双引号可以$str防止变量值发生分词和通配:"$str"扩展为 的值str。您可能会混淆双引号和单引号 -cat <<< '$str'将五个字符的字符串$str与最后的换行符作为输入传递给cat.

相关内容