Question

I need to make this script create and then output to an html file data inside template.vars. The script is a template engine, but right now all it does is take in input from the keyboard, echoing out the name in template.vars when the input is @NAME@. Here is the code of the template engine at the moment:

#!/bin/bash
IFS=@  #makes @ a delimiter. 
while read line
do
  dataspace=$(awk '$0=$1' FS== <<< "$line")
    value=$(awk '$0=$2' FS== <<< "$line")
  printf -v $dataspace "$value"                     #make the value stored in value into the name of a dataspace.
done < 'template.vars' #read template.vars for standard input.
skipflag=false           #initialize the skipflag to false                       
while read line                                 #while it is reading standard input one line at a time
do
  read -a dataspacearray <<< "$line"                #make the line into an array.
  if [ $skipflag == false ] && [ "${dataspacearray[1]}" != "ENDIF" ] ; then
        if [[ ${dataspacearray[1]} == "IF "* ]] ; then #If second element of dataspacearray is "IF "(something)
          dataspace=`echo ${dataspacearray[1]} | cut -d' ' -f2`
          if [ -z "${!dataspace}" ] ; then                #if dataspace not found, skip everything up to endif. -z to test string
            skipflag=true
            fi
        else
          for ((i=0; i<${#dataspacearray[@]}; i++))
          do
            dataspace=${dataspacearray[i]}                    #access to each dataspace in the array
            even=`expr $i % 2`  
                    if [ $even == '0' ] ; then                #if it's even(f0,f2, f4.. etc. etc) then it's not a variable, so print it directly
              if [ -n "${dataspace}" ] ; then
                printf ${dataspace}
              fi
            else                                      #(odd dataspaces(f1, f3... etc.) are variables, print their values if they exist
              if [ -n "${!dataspace}" ] ; then
                printf ${!dataspace}
              else
                printf "Error!!!"
              fi
            fi
          done
          printf "\n"
        fi
  else     
    skipflag=false
  fi
done

The html file goes in as input like this:

<html>
  <head>
    <title>@NAME@</title>
  </head>
  <body>
    <p>Name: @NAME@</p>
    <p>Major: @MAJOR@</p>
    <p>Classification: @CLASS@</p>
    <p>Graduation date: @GDATE@</p>
@IF HONORS@
    <p>Graduating with Honors</p>
@ENDIF@
  </body>
</html>

With the script replacing all strings beginning and ending with @ using the data in the template.vars file (or outputting error!!! if that isn't found). I have seen many instances where templates replace any text that has $ at the beginning, and think that I need to implement something similar, but with it reading the html file as input, and then saving it as output. How do I do this?

Was it helpful?

Solution

This isn't strictly what you asked for, but it's probably close enough to give you something to work with.

Leaving aside the @IF ...@ ... @ENDIF@ handling (which is a mostly untested afterthought), The logic goes something like this:

For each input line

1) initilise an empty holding space

2) if the line has fewer than two delimiters, goto #10

3) copy from the start of the line up to (but not including) the first delimiter to the hold space

4) remove the first segment of the line (including the delimiter). The leading segment of the line should now be a token.

5) copy the token (up to the delimiter) to a temporary variable

6) remove the token from the line (leave the trailing delimiter in place)

7) look up the token in a list of known tokens.

8) if it's a known token, append the token's expansion to the hold space and remove the delimiter from the line. If the token is unknown, append the delimiter (removed at #4) and the token text to the hold space but leave the non-token's trailing delimiter at the start of the line -- this is to allow (@name@@@domain@) and multiple runs with different variable definition files (./expstuff -v user.vars < template.in | ./expstuff -v global.vars > outputfile) but will need changing for your requirement.

9) goto #2

10) print hold space and whatever remains of the line.

typeset -A s

i=template.vars
d=@

while IFS='=' read t v ; do
  [[ $t != \#* ]] && s[$t]=$v
done < "$i"

while IFS= read -r l ; do
  #  assuming the @IF blah@ and corresponding @ENDIF@ occupy entire lines.
  if [[ $l == $d[Ee][Nn][Dd][Ii][Ff]$d ]]; then
    c=''
    continue
  fi
  [[ $c == '0' ]] && continue
  if [[ $l == $d[Ii][Ff][[:space:]]*[![:space:]]*$d ]]; then
    read _ t <<< "${l%$d}"
    c=0
    if [[ -n $t && ${s[$t]+t} == 't' ]]; then
      case ${s[$t]} in [Yy]|[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1 ) c=1 ;; esac
    fi
    continue
  fi

  # Currently, given
  #   foo@domain@TLD@ wibble
  # with TLD=.co.uk
  # the following loop outputs
  #   foo@domain.co.uk wibble
  # You appear to require
  #   fooError!!!TLD@wibble

  h=
  while [[ $l == *$d*$d* ]]; do
    h=$h${l%%$d*}
    l=${l#*$d}
    t=${l%%$d*}
    l=${l#$t}
    if [[ -n $t && ${s[$t]+t} == 't' ]]; then
      h=$h${s[$t]}
      l=${l#$d}
    else
      h=$h$d$t
      # for apparent requirement change preceding line to (untested)
      # h=$h"Error!!!" ; l=${l#$d}
    fi
  done
  printf '%s\n' "$h$l"
done
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top