Fill placeholders in file in single pass

前端 未结 5 1742
旧时难觅i
旧时难觅i 2021-02-09 23:11

I have a skeleton text file with placeholder strings:

blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$

and so on. Specific \"form\" of

相关标签:
5条回答
  • 2021-02-09 23:33

    I just stumbled upon this question because I was just looking for the exact same, and I found envsubst(1).

    You can use envsubst if you don't mind using environment variables:

    PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline 
    string 
    2' envsubst < output.template 
    

    If you have a lot of variables you can store them in a file and just source it (remember to use export at the end of the sourced file!)

    0 讨论(0)
  • 2021-02-09 23:41

    Building on the previous answer, perhaps use an array and compute the sed string?

    #!/bin/sh
    PLACEHOLDER[0]='string 1'
    PLACEHOLDER[1]='multiline 
    string 
    2'
    
    s="sed -i "
    for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do 
        echo ${PLACEHOLDER[$i]}
        s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;"
    done
    echo $s
    

    Seems to fail on the multi-line strings, though.

    I don't know how portable Bash arrays might be. Above snippet tested with "GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)"

    0 讨论(0)
  • 2021-02-09 23:41

    My bash only solution:

    TEMPLATE='
    foo
    $var1
    bar
    $var2'
    eval "echo \"$TEMPLATE\""
    
    0 讨论(0)
  • 2021-02-09 23:42

    You can still use sed to do the replace in a single pass. You just need to specify all the replacements in one command.

    eg.

    sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>
    
    0 讨论(0)
  • 2021-02-09 23:51

    Here's a way to do it without sed:

    First, a slightly modified template file in which the placeholders are bash variables:

    blah blah blah
    blah $PLACEHOLDER_1
    blah
    $PLACEHOLDER_2
    

    And the script:

    #! /bin/sh
    templatefile=output.template
    outputfile=output.txt
    
    PLACEHOLDER_1='string 1'
    
    PLACEHOLDER_2='multiline 
    string 
    2'
    
    # DONE: Generate file output.txt from file output.template 
    #       using placeholders above.
    
    echo "$(eval "echo \"$(cat $templatefile)\"")" > $outputfile
    

    Here's a version that demonstrates a template contained within the script, but with a twist. It also demonstrates default values, which can also be used in the template file version, plus you can do math in the template:

    #! /bin/sh
    template='blah blah blah
    blah $PLACEHOLDER_1
    blah
    ${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some
    lines
    of
    text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'
    # default operands to zero (or 1) to prevent errors due to unset variables
    outputfile=output.txt
    
    # gears spin, bells ding, values for placeholders are computed
    
    PLACEHOLDER_1='string 1'
    
    PLACEHOLDER_2='multiline 
    string 
    2'
    
    VAL_1=2
    
    VAL_2=4
    
    unset PLACEHOLDER_3 # so we can trigger one of the defaults
    
    # Generate file output.txt from variable $template 
    #       using placeholders above.
    
    echo "$(eval "echo \"$template\"")" > $outputfile
    

    No sed, no loops, just hairy nesting and quotes. I'm pretty sure all the quoting will protect you from malicious stuff in a template file, but I'm not going to guarantee it.

    0 讨论(0)
提交回复
热议问题