shell 将如何扩展此处文档中的包含内容?

shell 将如何扩展此处文档中的包含内容?

我有一个扭曲的外壳逻辑案例要提交给您,因为我在任何地方都没有发现任何关于该特定点的信息(如果我错过了,请接受我的道歉)。我会尽力解释上下文。

我有一个第一个scriptA,我希望scriptB通过使用定界符生成第二个。我想在这个heredoc中包含两个项目:一个my_source文件包含,以及一些本地变量scriptA(用于在 内扩展scriptA,即)。这是一个例子:

脚本A:

#!/bin/sh
logfile=/path/to/my_logfile
scriptB=/path/to/my_script
cat > ${scriptB} << __EOF__
  . /path/to/my_source  #this is a shell script
  echo "Some text" | tee -a ${logfile}
__EOF__

我对上面代码片段的问题是:.指令上的 shell 扩展(即包含my_source)会发生在scriptA还是中scriptB

奖金:是否可以以某种方式指定一些部分这里的文档不应该被扩展吗?

注意:我尝试在这里兼容 POSIX 并避免 bash 细节

感谢您的见解!

编辑:答案是该.实用程序不应在 中的此处文档中触发scriptA。这是因为此处文档仅执行:

参数扩展、命令替换和算术扩展

.是一个 shell 特殊的内置实用程序,它没有扩展(就像所有 shell 内置程序一样,包括 bash、ksh、tcsh 特定的 (...) 内置程序)。

感谢@ilkkachu 的见解。

答案1

不,此处文档已大部分扩展就像双引号字符串一样

如果没有引用单词的任何部分,则应扩展此处文档的所有行以进行参数扩展、命令替换和算术扩展。

反斜杠还可以用来转义特殊字符。

关于引用的注释意味着类似的内容<<"EOF"会阻止扩展此处文档中的任何内容。在您的示例中,${logfile}在将输入传递给 之前,shell 将扩展对 的引用cat

如果您想包含命令的输出,您仍然可以使用命令替换,但如果您想要的只是这样,那么使用管道也是一个合理的选择。

答案2

Heredoc 不进行重新解释,或者您可以说,不运行其中的任何命令。它只是插入字符串。

因此,您的查询的答案是 -ingsource不会发生在定界文档内。

对于后者,您可以使用\ie、反斜杠来关闭您不希望通过定界文档扩展的字符的含义。

答案3

我知道这是非常旧的,但我在一次搜索中遇到了它,并想为其他人纠正它。

这里的文档可以使用带有反引号 ` 的命令替换或使用通常的 $() 表示法。因此,在您的情况下,您可以使用 $(. ./my_source) 获取 my_source 文件。

但是,根据您的描述,我相信您并不真正想要获取 my_source 文件。我对这篇文章的解释是,您的意图是包含 my_source 文件的内容,而不是执行 my_source 文件,这将导致其 stdout 被合并到 ScriptB 中。

为了符合 posix 标准,请使用 cat 命令替换。

#!/bin/sh

logfile=my_logfile
scriptB=my_script
cat > ${scriptB} << __EOF__
  $(cat my_source)  #this is a shell script
  echo "Some text" | tee -a ${logfile}
__EOF__

命令替换会创建一个子 shell,因此如果您可以接受 bashism,只需将整个文件读入变量,然后使用常规参数扩展即可。

#!/bin/bash

logfile=my_logfile
scriptB=my_script
IFS="" read -r -d '' my_source_var < my_source
cat > ${scriptB} << __EOF__
  ${my_source_var}  #this is a shell script
  echo "Some text" | tee -a ${logfile}
__EOF__

相关内容