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