Bash 如何将template.txt包含为脚本的here doc

Bash 如何将template.txt包含为脚本的here doc,bash,Bash,我有一个模板文件(template.txt): 我有一个脚本文件(script.sh): 如何将template.txt作为script.sh的here doc包含 因此,当我运行script.sh时,输出应该是: Hello, linux Hello, unix 编辑: 我认为replace对我的工作来说是一个很好的命令: $ cat template.txt | replace '$x' linux '$y' unix 更复杂的工具: $ cheetah compile templat

我有一个模板文件(
template.txt
):

我有一个脚本文件(
script.sh
):

如何将
template.txt
作为
script.sh的
here doc
包含

因此,当我运行
script.sh
时,输出应该是:

Hello, linux
Hello, unix

编辑:

我认为
replace
对我的工作来说是一个很好的命令:

$ cat template.txt | replace '$x' linux '$y' unix
更复杂的工具:

$ cheetah compile template.tmpl
$ x=linux y=unix python template.py --env

我在我的一个项目中使用此功能。它从模板构建一个实际的here文档,然后在当前shell中使用

# usage: apply_template /path/to/template.txt
apply_template () {
        (
        trap 'rm -f $tempfile' EXIT
        tempfile=$(mktemp $(pwd)/templateXXXXXX)

        echo 'cat <<END_TEMPLATE' > $tempfile
        cat $1 >> $tempfile
        echo END_TEMPLATE >> $tempfile

        . $tempfile
        )
}
用法:apply_template/path/to/template.txt 应用模板(){ ( 陷阱“rm-f$tempfile”退出 tempfile=$(mktemp$(pwd)/templateXXXXXX) 回显“cat
#!/bin/bash”
x=linux
y=unix
cat这可能适合您(GNU-sed):


cat下面的bash函数按照此处的文档计算任意文件,允许将bash用作迷你模板语言。它不需要任何临时文件

#!/bin/bash

template() {
  file=$1
  shift
  eval "`printf 'local %s\n' $@`
cat <<EOF
`cat $file`
EOF"
}
和片段

y=42
for i in 1 2; do
  template template.txt x=$i z=end
done
输出将是

Hello 1, 42, end
Hello 2, 42, end

请注意,模板文件中的任意代码也将被执行,因此请确保您信任编写它的人。

以下是我建议的解决方案:

eval $'cat <<\002\n'"$(<ifile)"$'\n\002' > ofile

此解决方案似乎可以解决大多数问题,但特别容易通过
$(command)在模板文件中插入命令
指令。

是否必须自动检测并插入可用的变量?使用
sed
简单地替换出现的
$x
$y
有什么问题?随着变量数量的增加,这种方法变得更难管理。也很难保持所有引用的正确性。是这样吗在模板中使用实际的here文档有什么不对?@larsks:变量名可以存储在列表中,因此(a)比使用任何变量名更安全,(b)更安全flexible@NiklasB.也许你可以举个例子而这一切都是不存在的,所以评论长度的要求。只是想注意,有些人实际上让其他人编写他们的模板;)
#!/bin/bash

template() {
  file=$1
  shift
  eval "`printf 'local %s\n' $@`
cat <<EOF
`cat $file`
EOF"
}
Hello $x, $y, $z
y=42
for i in 1 2; do
  template template.txt x=$i z=end
done
Hello 1, 42, end
Hello 2, 42, end
eval $'cat <<\002\n'"$(<ifile)"$'\n\002' > ofile
eval $'cat <<\002\n'"$(tr -d '\002' < ifile)"$'\n\002' > ofile