有人可以帮忙吗?
我想通过从另一个文本文件中读取如下命令来在Shell脚本中执行一些命令:
command_file.txt包含:
EXECUTED_OK_$(date)
EXECUTED_OK_$(hostname)
shell script.sh
#!/bin/sh
while read command
do
echo $command
done < command_file.txt
我的问题是,echo像命令文件中一样是文本。 如何使其展开并打印实际日期和主机名。
例如 预期输出应为:
EXECUTED_OK_22-02-2010 11:10:10
EXECUTED_OK_localhost
但是我得到了:
EXECUTED_OK_$(date)
EXECUTED_OK_$(hostname)
答案 0 :(得分:1)
使用eval
扩展变量并重新执行。
$ foo='EXECUTED_OK_$(date)'
$ echo $foo
EXECUTED_OK_$(date)
$ eval "echo $foo"
EXECUTED_OK_Tue May 21 12:39:45 PDT 2019
编辑:eval
功能强大,但可能很危险;基本上是代码注入。引用论点是一个好主意。有关更多说明,请参见下面的评论。
答案 1 :(得分:0)
此白名单方法将不允许像eval
那样执行任意代码。如果安全性不是问题,则应坚持使用eval
,因为此示例中使用的外部组件有很多极端情况,因此替换无法按预期进行。
在打印命令之前,程序用其输出替换命令文件的每个命令中引用的某些外部变量:
#!/bin/bash
while read command
do
while read -a external ; do
output=$( "${external[@]}" )
command=$( sed "s/\$(${external})/${output}/g" <<< "$command" )
done <<END
date -R
hostname
END
echo "$command"
done < command_file.txt
要使用更多外部组件,您需要将它们添加到<<END
和END
之间的heredoc中。我在-R
中添加了date
,以展示带有参数的外部对象。
正如已经指出的那样,将不会在外部命令上进行除单词拆分之外的任何处理(例如,引号,替换)(可以将空格转义(one\ two
而不是引用)。
答案 2 :(得分:0)
一种选择是使用eval
,假设您信任输入文件
#!/bin/sh
while read command; do
eval "echo $command"
done < command_file.txt