shell调用的程序是否继承了shell变量?

the*_*fog 2 shell quoting

如果我有这个 shell 脚本

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

cat <<< "$str"
Run Code Online (Sandbox Code Playgroud)

我的理解是命令

cat <<< "$str"
Run Code Online (Sandbox Code Playgroud)

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

Rob*_*rtL 7

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

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

在类 Unix 操作系统中,大多数新程序的执行都是由于execve()系统所有:

int execve(const char *filename, char *const argv[], char *const envp[]);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

Here String 类似于传统的成语:

echo "$str" | cat
Run Code Online (Sandbox Code Playgroud)

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

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


Gil*_*il' 5

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.