Partager via


Powershell Template Engine

A template engine that allows you to have powershell expressions in your templates is a very powerful thing: https://weblogs.asp.net/soever/archive/2006/12/31/a-templating-engine-using-powershell-expressions.aspx

Example Input:

Multi Line Expression:
[[ get-date
1..20
]]

Define function [[ function get-theanswer {42;} ]]

Single Line: [[ theanswer ]]

EOF

Example Output:

Multi Line Expression:
03/14/2007 22:38:09 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Define function

Single Line: 42

EOF

The implementation uses dynamic code generation to build an assembly in order to have a delegate to pass to regex.replace. 

Using code generation felt a bit over complicated, and I wondered if it could be simpler.

Some thinking and tinkering later, I arrived at a working implementation.

Getting the multiline regex expression working correctly caused me some difficulty; as it only seems to correctly handle \R as a line separator.

I also added the ability to pipe text to the script, since I like to use the syntax: gc file.txt | expand-template

Now as with any powerful tool you'll need to be careful, and be sure that you fully trust the template file (other wise you'll be vulnerable to a code injection attack)

Expand-Template.ps1:

 param ($text="",$BeginTag='[[',$EndTag=']]') 
$begintag = [regex]::escape($begintag) 
$endtag = [regex]::escape($endtag) 
$output="" 

$input | %{$text+=[string]$_ + "`r"} 

while ($text -match "(?m)(?<pre>.*?)$begintag(?<exp>.*?)$endtag(?<post>.*)") { 
  $text = $matches.post 
  $output += $matches.pre 
  $output += invoke-expression $matches.exp 
} 

$output += $text 
$output -replace "`r", [environment]::newline