2

I have a mustache like template file that needs to be parsed. e.g.

abc def ghijk{{ var1 }} lmno {{ var2 }} pq
rst={{ var3 }} uvwzyx

Variables like {{ var1 }} need to be replaced by a variable with the same name, which is already defined previous in the bash script, e.g var1="foobar".

I am thinking of using while read and awk to accomplish this, but don't know what is the correct way to do string manipulation in this case.

Thanks in advance!

Gordon Yuan Gao
  • 694
  • 6
  • 20
  • Are you expecting the awk to be able to handle things like partials and render blocks etc? I think you're better off trying something like [this](http://stackoverflow.com/questions/12092641/how-to-run-debug-javascript-in-command-line) and using mustache.js in a local js file. – n0741337 Apr 17 '14 at 16:54
  • @n0741337 No, not that much, just simple variable substitution is enough. And for some reason, I cannot use third-party libraries but only pure bash/awk/sed. – Gordon Yuan Gao Apr 17 '14 at 16:58
  • Show your expected output along with how the mapping of var1, etc. are stored. – Ed Morton Apr 17 '14 at 21:04

4 Answers4

2
export var1="duper"
export var2="tester"
export var3=1231
sed -e 's/{{ *\([^} ]*\) *}}/$\1/g' -e 's/^/echo "/' -e 's/$/"/' input | sh

Gives:

abc def ghijkduper lmno tester pq
rst=1231 uvwzyx
perreal
  • 94,503
  • 21
  • 155
  • 181
  • This works! Thanks! just FYI, since my data file may contain double quotes therefore I need to do an extra round of replace of `-e 's/"/\\"/g'`. Can you explain what does `[^} ]*` mean in your answer? – Gordon Yuan Gao Apr 18 '14 at 10:53
  • 1
    `[^} ]*` means any character except a `}` or a space. – perreal Apr 18 '14 at 11:16
1

Here's an all awk version that requires a file of key=value pairs for the replacements. If I make a vars file like:

 var1 =foobar
 var2 =elf
 var3 =monkey data

where I "cheated" and included the whitespaces associated with vars in your data file. Then I made an executable awk file like:

#!/usr/bin/awk -f

BEGIN {FS="="}
NR==FNR {vars[$1]=$2; next}

set_delims==0 {FS="[{][{]|[}][}]"; $0=$0; set_delims=1 }

{
    for(i=1;i<=NF;i++) {
        printf( "%s%s", ($i in vars) ? vars[$i] : $i, i==NF?"\n":"")
    }
}

If the executable awk file is called awko it can be run like awko vars data:

abc def ghijkfoobar lmno elf pq
rst=monkey data uvwzyx
n0741337
  • 2,474
  • 2
  • 15
  • 15
1

I had a similar issue recently and found this nice mustache implementation in bash: https://github.com/tests-always-included/mo

If you have all your variables already defined in the current bash context it's as simple as calling:

./mo template.file

With a slightly different usage it also supports other mustache features like partials or arrays.

schneidexe
  • 31
  • 4
0

To do this in a scalable manner (lots of macros to expand), you'll probably want to look into using a macro processor. GNU m4 springs to mind, though it only allows alphanumeric and _ characters in macro names, so may be tricky for this particular task.

To get you started, you can use sed to do the replacements with this sed script (I called it mustache.sed):

s/{{ var1 }}/foobar/g
s/{{ var2 }}/bazbar/g
s/{{ var3 }}/quxbar/g

In use with your example:

$ sed -f mustache.sed mustache.txt
abc def ghijkfoobar lmno bazbar pq
rst=quxbar uvwzyx
$ 

You could put this sed script all on one sed command line, but I think using the script makes it more readable.

Digital Trauma
  • 15,475
  • 3
  • 51
  • 83