dtz33344 2015-06-10 16:59
浏览 80

仅模板变量替换。 文字/模​​板是否合适?

I'm looking for an efficient way to replace a bunch of placeholders/tokens in a user supplied text file, with their corresponding values stored in a simple map or environment vars. The thing is that the template file will be supplied by the end user, so I'm looking for a "safe" way to do only the variable replacements, without any risk of code execution, etc.

Go's standard "text/template" would work for the replacement itself but imposes specific formatting requirements (e.g. dot "." before the Key) and opens up other possibilities with its function invocations, pipelines, etc.

So what I'm looking for, ideally, is a function that can parse a text file with configurable delimiters ("{{}}" or "${}" or "$##$") and replace all the detected tokens with lookups into a supplied map or their env var values. Similar to what Python's string.Template (https://docs.python.org/2.6/library/string.html?highlight=string.template#string.Template) does.

Is there an easy way to configure or reuse the text/template library for this? Are there any other approaches that would fit the use case better? I've looked into non-golang options as well (like envsubtr, awk and sed scripts etc.) so feel free to go outside of Go if something fits better.

Sample input file ('template.properties'):

var1=$#VAR_1#$
var2=$#VAR_2#$

Sample input data:

VAR_1 = apples
VAR_2 = oranges

Expected output after processing:

var1=apples
var2=oranges
  • 写回答

2条回答 默认 最新

  • douzhi7661 2015-06-10 20:16
    关注

    This will work as long as your variable names don't contain ERE metacharacters:

    $ 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
    

    wrt your comment below about having the mappings in variables instead of in input.data, this might be what you're looking for:

    $ 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
    }
    

    will work with shell variables like:

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

    or:

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

    or:

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

    Note that this is gawk-specific due to ENVIRON and requires VAR_1 etc. to be exported or set on the command line as I have it above.

    Or maybe this is what you want:

    $ 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
    
    评论

报告相同问题?