0

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?

1 Answer 1

1

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
  #   [email protected] 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
Sign up to request clarification or add additional context in comments.

1 Comment

Its a bit late, but thanks. I figured some of it out partially on my own by basically just trial and erroring it to death. Didn't completely fix it as much as I liked (the HONORS output portion was a little weird, outputting that a person was in honors if the text file simply had the string HONORS=(anything aside from no other characters, if FALSE, it output the HONORS like it was true, if =bla, true. The only time it seemed to act if honors was false is if nothing was entered. Other then that, I got it working near perfectly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.