Python 仅模板变量替换。文本/模板是否适合?

Python 仅模板变量替换。文本/模板是否适合?,python,awk,sed,go,go-templates,Python,Awk,Sed,Go,Go Templates,我正在寻找一种有效的方法来替换用户提供的文本文件中的一组占位符/令牌,并将其相应的值存储在一个简单的映射或环境变量中。问题是模板文件将由最终用户提供,因此我正在寻找一种“安全”的方法,只进行变量替换,而不存在任何代码执行风险,等等 Go的标准“文本/模板”将适用于替换本身,但规定了特定的格式要求(例如,键前的点“.”),并通过其函数调用、管道等打开了其他可能性 因此,理想情况下,我要寻找的是一个函数,它可以用可配置的分隔符(“{}}”或“${}”或“$##$”)解析文本文件,并用对提供的映射或其

我正在寻找一种有效的方法来替换用户提供的文本文件中的一组占位符/令牌,并将其相应的值存储在一个简单的映射或环境变量中。问题是模板文件将由最终用户提供,因此我正在寻找一种“安全”的方法,只进行变量替换,而不存在任何代码执行风险,等等

Go的标准“文本/模板”将适用于替换本身,但规定了特定的格式要求(例如,键前的点“.”),并通过其函数调用、管道等打开了其他可能性

因此,理想情况下,我要寻找的是一个函数,它可以用可配置的分隔符(“{}}”或“${}”或“$##$”)解析文本文件,并用对提供的映射或其env var值的查找来替换所有检测到的标记。与Python的
string.Template
()类似

是否有一种简单的方法来配置或重用文本/模板库?还有其他更适合用例的方法吗?我也研究过非golang选项(如
envsubtr
awk
sed
脚本等),所以如果适合的话,可以自由选择go之外的选项

示例输入文件('template.properties'):

var1=$#VAR_1#$
var2=$#VAR_2#$
VAR_1 = apples
VAR_2 = oranges
var1=apples
var2=oranges
样本输入数据:

var1=$#VAR_1#$
var2=$#VAR_2#$
VAR_1 = apples
VAR_2 = oranges
var1=apples
var2=oranges
处理后的预期输出:

var1=$#VAR_1#$
var2=$#VAR_2#$
VAR_1 = apples
VAR_2 = oranges
var1=apples
var2=oranges

只要变量名不包含ERE元字符,这将起作用:

$ cat tst.awk
NR==FNR { var2val[$1] = $NF; next }
{
    for (var in var2val) {
        sub("[$]#"var"#[$]",var2val[var])
    }
    print
}

$ awk -f tst.awk input.data template.properties
var1=apples
var2=oranges
请在下面写下您关于在变量中而不是在input.data中进行映射的评论,这可能就是您要寻找的:

$ cat tst.awk
BEGIN {
    split(vars,tmp)
    for (i in tmp) {
        var2val[tmp[i]] = ENVIRON[tmp[i]]
    }
}
{
    for (var in var2val) {
        sub("[$]#"var"#[$]",var2val[var])
    }
    print
}
将使用shell变量,如:

$ VAR_1=apples VAR_2=oranges gawk -v vars="VAR_1 VAR_2" -f tst.awk template.properties
var1=apples
var2=oranges
或:

或:

请注意,由于环境的原因,这是特定于gawk的,并且需要在命令行上导出或设置VAR_1等,正如上面所述

或者这就是你想要的:

$ cat tst.awk
BEGIN {
    var2val["VAR_1"] = VAR_1
    var2val["VAR_2"] = VAR_2
}
{
    for (var in var2val) {
        sub("[$]#"var"#[$]",var2val[var])
    }
    print
}

$ VAR_1=apples
$ VAR_2=oranges
$ awk -v VAR_1="$VAR_1" -v VAR_2="$VAR_2" -f tst.awk template.properties
var1=apples
var2=oranges

只需使用fasttemplate[1]。它完全符合您的要求:

  • 可以使用任意占位符的开始和结束分隔符
  • 不可信输入的风险为零,因为除了占位符的替换之外,没有任何逻辑
  • 工作速度比文本/模板快得多(10倍)

[1]

您可以手动读取文件并对变量/替换执行后续替换操作,通过动态构建输出,您可以高效地执行此操作。它可以用相当少的代码行(~30行)完成。请看这个用Java表示的问题+答案:谢谢icza。实现我自己的替换程序无疑是一种选择,但我希望找到一个高效灵活的库来实现它。替换字符串中的标记似乎是一项非常普通的任务,其他人可能已经很好地解决了。类似的任务对您有用吗?n0741337,胡子是一个很好的选择。我没有想到要寻找一个围棋的实现。但是,它仍然支持“Sections”,语法类似于
{{{{}
。你知道有没有办法禁用该片段吗?你可以预过滤输入(不管怎样,这是个好主意),如果它包含{{{{}谢谢你的代码片段@EdMorton。我目前在数据结构(Go或Python程序)中有源var/值或者环境变量。我可以将var数据写入临时文件,以便按照建议工作。是否有一种简单的方法“传入”数据,或者让awk脚本从导出的shell环境变量中查找数据,而不需要使用它创建临时文件?抱歉,我从未听说过“Go”而且不能区分Python程序和地上的洞当你说“env vars”-你是在谈论shell变量还是其他什么?不管是什么,请编辑你的问题以显示它。@Ike我编辑我的问题是为了展示一些可能的解决方案,以解释你关于在env vars中有值的评论的一种可能的解释。再次感谢@EdMorton。这看起来是一种很好的、实用的方法。我没有想过通过var在命令行中命名,但它很容易以编程方式进行,并且作为输入过滤器也很有帮助。我将使用几个真实的模板文件对其进行测试并报告。