使用 bash 脚本从模板创建新文件

发布于 2024-11-12 17:06:50 字数 439 浏览 3 评论 0原文

我必须创建非常相似的conf 文件和init.d。这些文件允许在我的服务器上部署新的 HTTP 服务。这些文件是相同的,只有一些参数从一个文件更改为另一个文件(listen_port、域和服务器上的路径)。

由于这些文件中的任何错误都会导致服务功能障碍,我想创建这些文件使用 bash 脚本的文件。

例如:

generate_new_http_service.sh 8282 subdomain.domain.example /home/myapp/rootOfHTTPService

我正在寻找一种可以与 bash 一起使用的模板模块。该模板模块将使用一些通用的 confinit.d 脚本来创建新的脚本。

我可以使用 python 模板引擎吗?

I have to create conf files and init.d which are very similar. These files permit to deploy new HTTP service on my servers. These files are the same and only some parameters change from one file to another (listen_port, domain, and path on server.)

As any error in these files leads to dysfunction of service I would like to create these files using a bash script.

For example:

generate_new_http_service.sh 8282 subdomain.domain.example /home/myapp/rootOfHTTPService

I am looking for a kind of templating module that I could use with bash. This templating module would use some generic conf and init.d scripts to create new ones.

Could I could use python templating engine?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

生来就爱笑 2024-11-19 17:06:50

您可以使用定界符来做到这一点。例如

generate.sh

#!/bin/sh

#define parameters which are passed in.
PORT=$1
DOMAIN=$2

#define the template.
cat  << EOF
This is my template.
Port is $PORT
Domain is $DOMAIN
EOF

输出:

$ generate.sh 8080 domain.example

This is my template.
Port is 8080
Domain is domain.example

或将其保存到文件:

$ generate.sh 8080 domain.example > result

You can do this using a heredoc. e.g.

generate.sh:

#!/bin/sh

#define parameters which are passed in.
PORT=$1
DOMAIN=$2

#define the template.
cat  << EOF
This is my template.
Port is $PORT
Domain is $DOMAIN
EOF

Output:

$ generate.sh 8080 domain.example

This is my template.
Port is 8080
Domain is domain.example

or save it to a file:

$ generate.sh 8080 domain.example > result
莫多说 2024-11-19 17:06:50

bash 的模板模块?使用 sed,卢克!以下是数百万种可能方法之一的示例:

$ cat template.txt 
#!/bin/sh

echo Hello, I am a server running from %DIR% and listening for connection at %HOST% on port %PORT% and my configuration file is %DIR%/server.conf

$ cat create.sh 
#!/bin/sh

sed -e "s;%PORT%;$1;g" -e "s;%HOST%;$2;g" -e "s;%DIR%;$3;g" template.txt > script.sh

$ bash ./create.sh 1986 example.com /tmp
$ bash ./script.sh 
Hello, I am a server running from /tmp and listening for connection at example.com on port 1986 and my configuration file is /tmp/server.conf
$ 

Template module for bash? Use sed, Luke! Here is an example of one of millions of possible ways of doing this:

$ cat template.txt 
#!/bin/sh

echo Hello, I am a server running from %DIR% and listening for connection at %HOST% on port %PORT% and my configuration file is %DIR%/server.conf

$ cat create.sh 
#!/bin/sh

sed -e "s;%PORT%;$1;g" -e "s;%HOST%;$2;g" -e "s;%DIR%;$3;g" template.txt > script.sh

$ bash ./create.sh 1986 example.com /tmp
$ bash ./script.sh 
Hello, I am a server running from /tmp and listening for connection at example.com on port 1986 and my configuration file is /tmp/server.conf
$ 
他是夢罘是命 2024-11-19 17:06:50

您可以直接在 bash 中执行此操作,甚至不需要 sed。编写这样的脚本:

#!/bin/bash

cat <<END
this is a template
with $foo
and $bar
END

然后像这样调用它:

foo=FOO bar=BAR ./template 

you can do this directly in bash, you do not even need sed. Write a script like that:

#!/bin/bash

cat <<END
this is a template
with $foo
and $bar
END

then call it like so:

foo=FOO bar=BAR ./template 
淡淡の花香 2024-11-19 17:06:50

对于简单的文件生成,基本上这样做

 . "${config_file}"
 template_str=$(cat "${template_file}")
 eval "echo \"${template_str}\""

就足够了。

这里的 ${config_file} 包含 shell 可解析格式的配置变量,而 ${template_file} 是模板文件,看起来像 shell here 文档。第一行在文件 ${config_file} 中进行源代码,第二行将文件 ${template_file} 的内容放入 shell 变量 template_str 中>。最后,在第三行中,我们构建 shell 命令 echo "${template_str}" (其中双引号表达式 "${template_str}" 被展开)并对其求值。

有关这两个文件的内容示例,请参阅 https://serverfault.com/a/699377/120756

模板文件中的内容存在限制,或者需要执行 shell 转义。此外,如果模板文件是外部生成的,那么出于安全原因,您需要考虑在执行之前实施适当的过滤,这样当有人注入著名的 $(rm -rf /)< 时,您就不会丢失文件。 /code> 在模板文件中。

For simple file generation, basically doing

 . "${config_file}"
 template_str=$(cat "${template_file}")
 eval "echo \"${template_str}\""

would suffice.

Here ${config_file} contains the configuration variables in shell parseable format, and ${template_file} is the template file that looks like shell here document. The first line sources in the file ${config_file}, the second line puts the contents of the file ${template_file} into the shell variable template_str. Finally in the third line we build the shell command echo "${template_str}" (where the double quoted expression "${template_str}" is expanded) and evaluate it.

For an example of the contents of those two files, please refer to https://serverfault.com/a/699377/120756.

There are limitations what you can have in the template file or you need to perform shell escaping. Also if the template file is externally produced, then for security reasons you need to consider implementing a proper filtering prior to execution so that you will not for example lose your files when somebody injects the famous $(rm -rf /) in the template file.

泅人 2024-11-19 17:06:50

这是我最终采取的解决这个问题的方法。我发现它比上述一些方法更灵活,并且它避免了一些引号问题。

fill.sh:

#!/usr/bin/env sh

config="$1"
template="$2"
destination="$3"

cp "$template" "$destination"

while read line; do
    setting="$( echo "$line" | cut -d '=' -f 1 )"
    value="$( echo "$line" | cut -d '=' -f 2- )"

    sed -i -e "s;%${setting}%;${value};g" "$destination"
done < "$config"

模板:

Template full of important %THINGS%

"Note that quoted %FIELDS% are handled correctly"

If I need %NEWLINES% then I can add them as well.

配置:

THINGS=stuff
FIELDS="values work too!"
NEWLINES="those\\nnifty\\nlinebreaks"

结果:
充满重要内容的模板

"Note that quoted "values work too!" are handled correctly"

If I need those
nifty
linebreaks then I can add them as well.

Here's the approach that I ended up taking to solve this problem. I found it a little more flexible than some of the above approaches, and it avoids some of the issues with quotes.

fill.sh:

#!/usr/bin/env sh

config="$1"
template="$2"
destination="$3"

cp "$template" "$destination"

while read line; do
    setting="$( echo "$line" | cut -d '=' -f 1 )"
    value="$( echo "$line" | cut -d '=' -f 2- )"

    sed -i -e "s;%${setting}%;${value};g" "$destination"
done < "$config"

template:

Template full of important %THINGS%

"Note that quoted %FIELDS% are handled correctly"

If I need %NEWLINES% then I can add them as well.

config:

THINGS=stuff
FIELDS="values work too!"
NEWLINES="those\\nnifty\\nlinebreaks"

result:
Template full of important stuff

"Note that quoted "values work too!" are handled correctly"

If I need those
nifty
linebreaks then I can add them as well.
渡你暖光 2024-11-19 17:06:50

[编辑]我改变了几年前的原始答案。

我喜欢上面 FooF 的答案:
但是

,我不希望有一个中间变量来存储内存中模板文件的全部内容。

. "${config_file}"
eval "echo \"$(cat "${template_file}")\""

示例

创建模板文件。我们将其命名为 example.tpl

Hello, ${NAME}!
Today, the weather is ${WEATHER}. Enjoy!

创建一个配置文件来存储变量。让我们称之为 good.conf

NAME=John
WEATHER=good

现在,在要渲染模板的脚本中,您可以这样写:

#!/usr/bin/env bash

template_file=example.tpl
config_file=good.conf

. "${config_file}"
eval "echo \"$(cat "${template_file}")\""

# Or store the output in a file
eval "echo \"$(cat "${template_file}")\"" > out

您应该看到这个精彩的输出:)

Hello, John!
Today, the weather is good. Enjoy!

注意 eval

当你使用eval时,如果模板文件包含一些指令,它们就会被执行,这可能是危险的。例如,让我们使用以下内容更改上面的 example.tpl

Hello, ${NAME}!
Today, the weather is ${WEATHER}. Enjoy!

I'm a hacker, hu hu! Look, fool!
$(ls /)

现在,如果您渲染模板文件,您将看到以下内容:

Hello, John!
Today, the weather is good. Enjoy!

I'm a hacker, hu hu! Look, fool!
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

现在将文件 good.conf 编辑为有这个内容:

NAME=$(ls -l /var)
WEATHER=good

并渲染模板。您应该看到类似这样的内容:

Hello, total 8
drwxr-xr-x.  2 root root    6 Apr 11 04:59 adm
drwxr-xr-x.  5 root root   44 Sep 11 18:04 cache
drwxr-xr-x.  3 root root   34 Sep 11 18:04 db
drwxr-xr-x.  3 root root   18 Sep 11 18:04 empty
drwxr-xr-x.  2 root root    6 Apr 11 04:59 games
drwxr-xr-x.  2 root root    6 Apr 11 04:59 gopher
drwxr-xr-x.  3 root root   18 May  9 13:48 kerberos
drwxr-xr-x. 28 root root 4096 Oct  8 00:30 lib
drwxr-xr-x.  2 root root    6 Apr 11 04:59 local
lrwxrwxrwx.  1 root root   11 Sep 11 18:03 lock -> ../run/lock
drwxr-xr-x.  8 root root 4096 Oct  8 04:55 log
lrwxrwxrwx.  1 root root   10 Sep 11 18:03 mail -> spool/mail
drwxr-xr-x.  2 root root    6 Apr 11 04:59 nis
drwxr-xr-x.  2 root root    6 Apr 11 04:59 opt
drwxr-xr-x.  2 root root    6 Apr 11 04:59 preserve
lrwxrwxrwx.  1 root root    6 Sep 11 18:03 run -> ../run
drwxr-xr-x.  8 root root   87 Sep 11 18:04 spool
drwxrwxrwt.  4 root root  111 Oct  9 09:02 tmp
drwxr-xr-x.  2 root root    6 Apr 11 04:59 yp!
Today, the weather is good. Enjoy!

I'm a hacker, hu hu! Look, fool!
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
swapfile
sys
tmp
usr
var

如您所见,配置文件模板文件中的命令注入是可能的,这就是为什么您必须格外小心:

  • < strong>确定模板文件的内容:检查是否有命令注入。
  • 确定配置文件的内容:检查是否也没有命令注入。如果配置文件来自其他人,则在渲染模板之前您需要了解并信任该人。

想象一下,您是一个无密码 sudoer,呈现模板文件可能会导致使用适当的 rm -rf 破坏您的系统。

只要您控制这些文件的内容,就可以使用此 eval 模板。

如果您有外部(不受信任的)传入配置文件,您应该寻找模板引擎,它将隔离此类注入。例如,Jinja2 模板在 Python 中非常有名。

[Edit] I changed my answer from the original one, that was years ago.

I like the answer from FooF above:
https://stackoverflow.com/a/30872526/3538173

Yet, I prefer not to have an intermediary variable to store the whole content of the template file in memory.

. "${config_file}"
eval "echo \"$(cat "${template_file}")\""

Example

Create a template file. Let's call it example.tpl:

Hello, ${NAME}!
Today, the weather is ${WEATHER}. Enjoy!

Create a configuration file to store your variables. Let's call it good.conf:

NAME=John
WEATHER=good

Now, in the script where you want to render the template, you can write this:

#!/usr/bin/env bash

template_file=example.tpl
config_file=good.conf

. "${config_file}"
eval "echo \"$(cat "${template_file}")\""

# Or store the output in a file
eval "echo \"$(cat "${template_file}")\"" > out

You should see this wonderful output :)

Hello, John!
Today, the weather is good. Enjoy!

Caution with eval

When you use eval, if the template file contains some instructions, they will be executed, and it can be dangerous. For example, let's change the example.tpl above with this content:

Hello, ${NAME}!
Today, the weather is ${WEATHER}. Enjoy!

I'm a hacker, hu hu! Look, fool!
$(ls /)

Now, if you render your template file, you will see this:

Hello, John!
Today, the weather is good. Enjoy!

I'm a hacker, hu hu! Look, fool!
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

Now edit your file good.conf to have this content:

NAME=$(ls -l /var)
WEATHER=good

and render the template. You should see something like this:

Hello, total 8
drwxr-xr-x.  2 root root    6 Apr 11 04:59 adm
drwxr-xr-x.  5 root root   44 Sep 11 18:04 cache
drwxr-xr-x.  3 root root   34 Sep 11 18:04 db
drwxr-xr-x.  3 root root   18 Sep 11 18:04 empty
drwxr-xr-x.  2 root root    6 Apr 11 04:59 games
drwxr-xr-x.  2 root root    6 Apr 11 04:59 gopher
drwxr-xr-x.  3 root root   18 May  9 13:48 kerberos
drwxr-xr-x. 28 root root 4096 Oct  8 00:30 lib
drwxr-xr-x.  2 root root    6 Apr 11 04:59 local
lrwxrwxrwx.  1 root root   11 Sep 11 18:03 lock -> ../run/lock
drwxr-xr-x.  8 root root 4096 Oct  8 04:55 log
lrwxrwxrwx.  1 root root   10 Sep 11 18:03 mail -> spool/mail
drwxr-xr-x.  2 root root    6 Apr 11 04:59 nis
drwxr-xr-x.  2 root root    6 Apr 11 04:59 opt
drwxr-xr-x.  2 root root    6 Apr 11 04:59 preserve
lrwxrwxrwx.  1 root root    6 Sep 11 18:03 run -> ../run
drwxr-xr-x.  8 root root   87 Sep 11 18:04 spool
drwxrwxrwt.  4 root root  111 Oct  9 09:02 tmp
drwxr-xr-x.  2 root root    6 Apr 11 04:59 yp!
Today, the weather is good. Enjoy!

I'm a hacker, hu hu! Look, fool!
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
swapfile
sys
tmp
usr
var

As you can see, command injection in the configuration file and the template file is possible, and that's why you have to be extra careful:

  • be sure of the content of the template file: check that there is NO command injection.
  • be sure of the content of the configuration file: check that there is NO command injection as well. If the configuration file comes from someone else, you need to know and trust that person before rendering the template.

Imagine that you are a password-less sudoer, rendering the template file could result in ruining your system with a well-placed rm -rf.

As long as you control the content of these files, it is fine to use this eval templating.

If you have an external (untrusted) incoming configuration file, you should look for templating engine, that will isolate these kind of injection. For example, Jinja2 templating is quite famous in Python.

终弃我 2024-11-19 17:06:50

我最终使用了可供我使用的 envsubst 。它在大多数 Linux 系统上都可以通过 gettext 包广泛使用。我使用它是因为它将负责有选择地替换变量,并且我不必像 eval 那样在模板中转义它们。这是一个例子。

$ cat dbtemplate.xml
<DB>
        <hostname>$DBHOST</hostname>
        <port>$DBPORT</port>
        <database>$DBNAME</database>
</DB>

$ export DBHOST=mydbhost1 DBPORT=1234 DBNAME=mydb; envsubst< dbtemplate.xml
<DB>
        <hostname>mydbhost1</hostname>
        <port>1234</port>
        <database>mydb</database>
</DB>

I ended up using envsubst which was available for me. It is widely available on most Linux systems in the gettext package. I used this because it will take care of selectively replacing variables and I don't have to escape them in the template as with e.g. eval. Here is an example.

$ cat dbtemplate.xml
<DB>
        <hostname>$DBHOST</hostname>
        <port>$DBPORT</port>
        <database>$DBNAME</database>
</DB>

$ export DBHOST=mydbhost1 DBPORT=1234 DBNAME=mydb; envsubst< dbtemplate.xml
<DB>
        <hostname>mydbhost1</hostname>
        <port>1234</port>
        <database>mydb</database>
</DB>
寄意 2024-11-19 17:06:50

您可以使用 python class string.Template

$ echo 'before $X after' > template.txt

$ python  -c 'import string; print(string.Template(open("template.txt").read()).substitute({"X":"A"}))'

before A after

$  python  -c 'import string, sys; print(string.Template(open("template.txt").read()).substitute({"X":sys.argv[1]}))' "A"

这里 $X 是模板中的占位符,{"X":"A"} 是占位符到值的映射。在 python 代码中,我们从文件中读取模板文本,从中创建模板,然后用命令行参数替换占位符。

或者,如果您的计算机上安装了 Ruby,您也可以使用 Ruby 的 ERB。

$ echo "before <%= ENV['X'] %> after" > template.txt

$ X=A erb template.txt

before A after

这里 <%= ENV['X'] %> 是一个占位符。 ENV['X'] 从环境变量中读取值。 X=A 将环境变量设置为所需的值。

You can use python class string.Template

$ echo 'before $X after' > template.txt

$ python  -c 'import string; print(string.Template(open("template.txt").read()).substitute({"X":"A"}))'

before A after

or

$  python  -c 'import string, sys; print(string.Template(open("template.txt").read()).substitute({"X":sys.argv[1]}))' "A"

Here $X is a placeholder in the template and {"X":"A"} is a mapping of the placeholder to a value. In the python code we read the template text from the file, create a template from it, then substitute the placeholder with the command line argument.

Alternatively you can use Ruby's ERB, if Ruby is installed on your machine.

$ echo "before <%= ENV['X'] %> after" > template.txt

$ X=A erb template.txt

before A after

Here <%= ENV['X'] %> is a placeholder. ENV['X'] reads the value from the environment variable. X=A sets the environment variable to the desired value.

年华零落成诗 2024-11-19 17:06:50

使用 perl 编写的优雅而简短的解决方案

我使用 perl 将变量替换为其值:

export world=World beautiful=wonderful
echo 'I love you, $world! You are $beautiful.' >my_template.txt
perl -pe 's|\$([A-Za-z_]+)|$ENV{$1}|g' my_template.txt

输出: I love you, World!你太棒了

my_template.txt 可以包含以 $ 为前缀的变量。

Elegant and short solution in one line with perl

I use perl to replace variables with their values:

export world=World beautiful=wonderful
echo 'I love you, $world! You are $beautiful.' >my_template.txt
perl -pe 's|\$([A-Za-z_]+)|$ENV{$1}|g' my_template.txt

The output: I love you, World! You are wonderful.

my_template.txt can contain variables prefixed with $.

物价感观 2024-11-19 17:06:50

使用bash从模板生成bash脚本

这个问题需要

#!/usr/bin/env bash

# expected result

# header
a=1
b=2

# body
echo "a=$a and b=$b"

在模板文件sample.tpl.sh中严格分离变量数据(脚本头)和常量代码(脚本体),我只有一个模板变量#%TEMPLATE_CONSTANTS

#!/usr/bin/env bash

# template file

# header
#%TEMPLATE_CONSTANTS

# body
echo "a=$a and b=$b"
echo "here in the script body,
#%TEMPLATE_CONSTANTS
is not replaced"

大多数环境都缺少固定字符串编辑器,因此我使用 grepdd 创建了自己的“fsed”,以仅替换第一个匹配项#%TEMPLATE_CONSTANTS

#!/usr/bin/env bash

# template processor

# https://stackoverflow.com/a/69479243/10440128
fixedReplaceFirst(){ # aka fsed (fixed string editor)
  tplFile="$1"
  pattern="$2"
  replace="$3"
  match="$(grep -b -m 1 -o -E "$pattern" "$tplFile")"
  offset1=$(echo "$match" | cut -d: -f1)
  match="$(echo "$match" | cut -d: -f2-)"
  matchLength=${#match}
  offset2=$(expr $offset1 + $matchLength)
  dd bs=1 if="$tplFile" count=$offset1 status=none
  echo -n "$replace"
  dd bs=1 if="$tplFile" skip=$offset2 status=none
}

read -d '' replace <<EOF
a=1
b=2
EOF

fixedReplaceFirst "sample.tpl.sh" "^#%TEMPLATE_CONSTANTS$" "$replace"

相关

use bash to generate bash script from template

this problem calls for a strict separation of variable data (script header) and constant code (script body)

#!/usr/bin/env bash

# expected result

# header
a=1
b=2

# body
echo "a=$a and b=$b"

in the template file sample.tpl.sh, i have only one template variable #%TEMPLATE_CONSTANTS

#!/usr/bin/env bash

# template file

# header
#%TEMPLATE_CONSTANTS

# body
echo "a=$a and b=$b"
echo "here in the script body,
#%TEMPLATE_CONSTANTS
is not replaced"

most environments lack a fixed-string-editor, so i made my own "fsed" with grep and dd, to replace only the first match of #%TEMPLATE_CONSTANTS

#!/usr/bin/env bash

# template processor

# https://stackoverflow.com/a/69479243/10440128
fixedReplaceFirst(){ # aka fsed (fixed string editor)
  tplFile="$1"
  pattern="$2"
  replace="$3"
  match="$(grep -b -m 1 -o -E "$pattern" "$tplFile")"
  offset1=$(echo "$match" | cut -d: -f1)
  match="$(echo "$match" | cut -d: -f2-)"
  matchLength=${#match}
  offset2=$(expr $offset1 + $matchLength)
  dd bs=1 if="$tplFile" count=$offset1 status=none
  echo -n "$replace"
  dd bs=1 if="$tplFile" skip=$offset2 status=none
}

read -d '' replace <<EOF
a=1
b=2
EOF

fixedReplaceFirst "sample.tpl.sh" "^#%TEMPLATE_CONSTANTS
quot; "$replace"

related

白龙吟 2024-11-19 17:06:50

我建议 shtpl,一个 shell 模板系统:
https://github.com/dontsueme/shtpl

它有一个非常简单的语法,万无一失,并且只需要标准的 *nix 工具。

I suggest shtpl, a shell templating system:
https://github.com/dontsueme/shtpl

It has a very simple syntax, is foolproof and does only need standard *nix tools.

无风消散 2024-11-19 17:06:50

快速而优雅的解决方案,安全地支持完整的 shell 脚本。

tmpl.sh

#!/bin/sh

EOF=EOF
exec cat <<EOF | sh
cat <<EOF
$(cat $1 | \
    sed 's|\\|\\\\|g' | \
    sed 's|`|\\`|g' | \
    sed 's|\$|\\\$|g' | \
    sed "s|${OPEN:-<%}|\`eval echo |g" | \
    sed "s|${CLOSE:-%>}| 2>/dev/null \`|g")
$EOF
EOF

https: //gitlab.com/risserlabs/community/cinch/-/blob/main/src/tmpl.sh

只需在您想要模板化的任何文件上运行以下命令即可。

sh tmpl.sh file.txt.tmpl

file.txt.tmpl

uname: <% $(uname) %>
pwd: <% `pwd` %>
ls: $(ls)
df: `df`
SHELL: <% $SHELL %>
HOME: <% ${HOME} %>
USER: $USER
PATH: ${PATH}

输出将类似于以下内容。

uname: Linux
pwd: /home/clayrisser
ls: $(ls)
df: `df`
SHELL: /usr/bin/zsh
HOME: /home/clayrisser
USER: $USER
PATH: ${PATH}

如果您想编写模板文件,只需将输出重定向到新文件即可。

sh tmpl.sh file.txt.tmpl > file.txt

您可以通过设置OPENCLOSE来更改开始和结束字符。

file.txt.tmpl

uname: {{ $(uname) }}
pwd: {{ `pwd` }}
ls: $(ls)
df: `df`
SHELL: {{ $SHELL }}
HOME: {{ ${HOME} }}
USER: $USER
PATH: ${PATH}
OPEN="{{" CLOSE="}}" sh tmpl.sh file.txt.tmpl

Quick and elegant solution that safely supports full shell scripting.

tmpl.sh

#!/bin/sh

EOF=EOF
exec cat <<EOF | sh
cat <<EOF
$(cat $1 | \
    sed 's|\\|\\\\|g' | \
    sed 's|`|\\`|g' | \
    sed 's|\$|\\\$|g' | \
    sed "s|${OPEN:-<%}|\`eval echo |g" | \
    sed "s|${CLOSE:-%>}| 2>/dev/null \`|g")
$EOF
EOF

https://gitlab.com/risserlabs/community/cinch/-/blob/main/src/tmpl.sh

Simply run the following on any file you want to template.

sh tmpl.sh file.txt.tmpl

file.txt.tmpl

uname: <% $(uname) %>
pwd: <% `pwd` %>
ls: $(ls)
df: `df`
SHELL: <% $SHELL %>
HOME: <% ${HOME} %>
USER: $USER
PATH: ${PATH}

The output would be something like the following.

uname: Linux
pwd: /home/clayrisser
ls: $(ls)
df: `df`
SHELL: /usr/bin/zsh
HOME: /home/clayrisser
USER: $USER
PATH: ${PATH}

If you want to write the templated file, simply redirect the output to a new file.

sh tmpl.sh file.txt.tmpl > file.txt

You can change the open and close characters by setting OPEN and CLOSE.

file.txt.tmpl

uname: {{ $(uname) }}
pwd: {{ `pwd` }}
ls: $(ls)
df: `df`
SHELL: {{ $SHELL }}
HOME: {{ ${HOME} }}
USER: $USER
PATH: ${PATH}
OPEN="{{" CLOSE="}}" sh tmpl.sh file.txt.tmpl
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文