shell解析字符串

发布于 2025-01-02 03:52:36 字数 339 浏览 2 评论 0原文

我从带有 shell 脚本变量的文件中读取了一个字符串,并希望用像这样的函数中的值替换变量

hello.txt:
-------------
Hello $NAME


a.sh 
-------------
function printout
{
  echo ???somehow_parse??? $1
}

NAME=Joe
printout "$(cat hello.txt)"
NAME=Nelly
printout "$(cat hello.txt)"

。该示例不是最好的,但它描述了我的问题。换句话说:我可以使用 shell 作为模板引擎吗?

我正在使用 ksh。

I read a string from a file with shell script variables, and want to substitute the variables with values in a function like

hello.txt:
-------------
Hello $NAME


a.sh 
-------------
function printout
{
  echo ???somehow_parse??? $1
}

NAME=Joe
printout "$(cat hello.txt)"
NAME=Nelly
printout "$(cat hello.txt)"

The example is not the best, but it describes my problem. In other words: can I use shell as a template engine?

I am using ksh.

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

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

发布评论

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

评论(4

握住你手 2025-01-09 03:52:36

一般来说,我会选择使用 sed/awk 的搜索和替换方法,如 Kent 的回答这个答案

如果您想要仅使用 shell 的方法,那么标准方法是使用 eval。然而,这会带来安全风险。例如:

[me@home]$ cat hello.txt
hello $NAME; uname -a
[me@home]$ NAME="shawn"
[me@home]$ eval echo "`cat hello.txt`"   # DO NOT DO THIS!
hello shawn
Linux SOMEHOST 2.6.9-101.ELsmp #1 SMP Fri May 27 18:57:30 EDT 2011 i686 i686 i386 GNU/Linux

注意如何将命令注入到模板中!

但是,您可以使用此方法降低风险:

[me@home]$ eval "OUT=\"`cat hello.txt`\""
[me@home]$ echo $OUT
hello shawn; uname -a

请注意,这仍然不是万无一失的,因为仍然可以使用 $(cmd)`cmd` 注入命令

简而言之,只有当您了解风险并且可以控制/限制对模板文件的访问时,您才应该使用eval

以下是如何将其应用到脚本中的示例:

function printout {
    FILENAME=$1
    eval "OUT=\"`cat $FILENAME`\""
    echo $OUT
}

NAME=Joe
printout hello.txt
NAME=Nelly
printout hello.txt

In general, I would go for a search-and-replace approach using sed/awk such as that shown in Kent's answer or this answer.

If you want a shell-only approach, then the standard way would be to use eval. However, this poses a security risk. For example:

[me@home]$ cat hello.txt
hello $NAME; uname -a
[me@home]$ NAME="shawn"
[me@home]$ eval echo "`cat hello.txt`"   # DO NOT DO THIS!
hello shawn
Linux SOMEHOST 2.6.9-101.ELsmp #1 SMP Fri May 27 18:57:30 EDT 2011 i686 i686 i386 GNU/Linux

Notice how a command can be injected into the template!

You can however reduce the risk using this approach:

[me@home]$ eval "OUT=\"`cat hello.txt`\""
[me@home]$ echo $OUT
hello shawn; uname -a

Do note that this is still not foolproof as commands can still be injected using $(cmd) or `cmd`.

In short, you should use eval only if you understand the risks and can control/limit access to the template files.

Here's an example of how this can be applied in your script:

function printout {
    FILENAME=$1
    eval "OUT=\"`cat $FILENAME`\""
    echo $OUT
}

NAME=Joe
printout hello.txt
NAME=Nelly
printout hello.txt
指尖上的星空 2025-01-09 03:52:36

如果您确定模板文件的内容是完全安全的,即它不包含执行可能损害您的计算机的命令的字符串,那么您可以使用 eval

#!/bin/bash
NAME=Joe
TEMPLATE=$(cat hello.txt)
eval "echo $TEMPLATE"
NAME=Nelly
eval "echo $TEMPLATE"

示例输出:

HELLO Joe
HELLO Nelly

If you're sure that the contents of your template file is completely safe, that is, it doesn't contain a string to execute a command that might harm your computer, then you can use eval:

#!/bin/bash
NAME=Joe
TEMPLATE=$(cat hello.txt)
eval "echo $TEMPLATE"
NAME=Nelly
eval "echo $TEMPLATE"

Example output:

HELLO Joe
HELLO Nelly
半寸时光 2025-01-09 03:52:36

像这样?

kent$  head hello.txt t.sh
==> hello.txt <==
hello $name

==> t.sh <==
#!/bin/bash

function printout
{
  echo $1|awk -v name="$name" 'gsub(/\$name/,name)'
}
name=xxx
printout "$(cat hello.txt)"
name=yyy
printout "$(cat hello.txt)"

运行它:

kent$  ./t.sh
hello xxx
hello yyy

like this?

kent$  head hello.txt t.sh
==> hello.txt <==
hello $name

==> t.sh <==
#!/bin/bash

function printout
{
  echo $1|awk -v name="$name" 'gsub(/\$name/,name)'
}
name=xxx
printout "$(cat hello.txt)"
name=yyy
printout "$(cat hello.txt)"

run it:

kent$  ./t.sh
hello xxx
hello yyy
尛丟丟 2025-01-09 03:52:36

我认为最简单的解决方案是使用 basename 实用程序。

例如,如果您有以下字符串:a='/home/you/stuff/myfile.txt',您可以使用如下命令:

dirname $a
basename $a
basename $a .txt

并获得如下所示的输出:

/home/you/stuff
myfile.txt
myfile

I think the easiest solution is to use the basename utility.

For instance, if you have the following string: a='/home/you/stuff/myfile.txt' you could use commands like:

dirname $a
basename $a
basename $a .txt

and get output that looks like this:

/home/you/stuff
myfile.txt
myfile
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文