-2

Is it possible to put a loop inside my code? Want to plot a area for every day of the current month and save to a file. One way is to hardcode it but that's no fun, and kind of impractical due to the number of days each month. Want to put in something like a "for each day of mont ..." or like "while day < lastDay ...."

    #!/bin/bash
    # genererar stapeldiagram för nuvarade månad
    # sparar fil enl. YYYY-MM-bar.png
    # använd tex. crontab 1min.
    # om script körs manuellt, sudo

    #TODO: argument för specefik månad enl. "$ simple_bar_generator.sh YYYY-MM"

    month=$(date +%m)
    day=$(date +%d)
    monthStr=$(date -d "-$(date +%d) days +1 month" +%B)
    year=$(date +%Y)
    firstDay=$(date -d "-0 month -$(($(date +%d)-1)) days" +%Y%m%d)        #YYYY-MM-DD
    lastDay=$(date -d "$firstDay + 1 month - 1 day" +%Y%m%d)               #YYYY-MM-DD

    source /etc/elmatare.conf
    imgPath="/var/www/img/"
    tempPath="/tmp/$year-$month-bar.png"
    /usr/bin/rrdtool graph $tempPath \
       --start $firstDay \
       --end $lastDay \
       --width 1600 \
       --height 400 \
       --title 'Förbrukning $monthStr Högmora 4:4' \
       --vertical-label 'kWh' \
       --alt-y-grid \
       --right-axis 1:0 \
       --units-exponent 2 \
       --color GRID#00000050 \
       --color MGRID#00000080 \
   while [ $firstDay -le $lastDay ]; do
       DEF:tot=$powerDBPath:Tot:AVERAGE:start=YYYYMMDD:end=YYYYMMDD \
       CDEF:w=tot,3600,* \
       CDEF:energiK=tot,1000,/ \
       VDEF:value_sum=energiK,TOTAL \
       CDEF:value_area=w,w,-,value_sum,+ \
       AREA:value_area#AAAAee \
       LINE1:value_area1#000000 \
       GPRINT:value_sum:"For testing purposes $day: %0.2lfkWh" \
   done
    mv $tempPath $imgPath

Have no luck!

$ ./simple_bar_generator.sh 
./simple_bar_generator.sh: line 31: syntax error near unexpected token `do'
./simple_bar_generator.sh: line 31: `while [ $firstDay -le $lastDay ]; do'

final loop looks like: adding index for variables, rrdtool do not accept reuse of variables.

args=( )
day=$firstDay
i=1
while [[ $day != $(date -d "$lastDay + 1 days" +%Y%m%d) ]]; do    
  dayStop=$(date -d "$day + 1 days" +%Y%m%d)
  args+=(
   DEF:tot$i="$powerDBPath:$DS:AVERAGE:start=$day:end=$dayStop"
   CDEF:w$i=tot$i,3600,"*"
   CDEF:energiK$i=tot$i,1000,/
   VDEF:value_sum$i=energiK$i,TOTAL
   CDEF:value_area$i=w$i,w$i,-,value_sum$i,+
   AREA:value_area$i#AAAAee
   LINE1:value_area$i#000000
   GPRINT:value_sum$i:"Förbrukning (för testning) $day %0.2lfkWh\n"
 )
 day=$(date -d "$day + 1 days" +%Y%m%d)
 i=$[$i+1]
done

1 Answers1

0

Generate your argument list beforehand, like so:

args=( )
day=$firstDay
while [[ $day <= $lastDay ]]; do
  args+=(
   DEF:tot="$powerDBPath:Tot:AVERAGE:start=YYYYMMDD:end=YYYYMMDD"
   CDEF:w=tot,3600,"*"
   CDEF:energiK=tot,1000,
   VDEF:value_sum=energiK,TOTAL
   CDEF:value_area=w,w,-,value_sum,+
   "AREA:value_area#AAAAee"
   "LINE1:value_area1#000000"
   GPRINT:value_sum:"For testing purposes $day: %0.2lfkWh"
 )
 day=$(date -d "$day + 1 days" +%Y%m%d)
done

...and then, after the loop has finished, run your command expanding the array it generated:

rrdtool static-args-here "${args[@]}"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • `args=( ) day=$firstDay i=1 while [[ $day != $lastDay ]]; do dayStop=$(date -d "$day + 1 days" +%Y%m%d) args+=( DEF:tot$i="$powerDBPath:Tot:AVERAGE:start=$day:end=$dayStop" CDEF:w$i=tot$i,3600,"*" CDEF:energiK$i=tot$i,1000,/ VDEF:value_sum$i=energiK$i,TOTAL CDEF:value_area$i=w$i,w$i,-,value_sum$i,+ AREA:value_area$i#AAAAee GPRINT:value_sum$i:"For testing purposes $day %0.2lfkWh" ) day=$(date -d "$day + 1 days" +%Y%m%d) i=$[$i+1] done` – Christofer Andersson Oct 18 '14 at 20:57
  • but you must agree that posting code in the comment section looks awful – Christofer Andersson Oct 18 '14 at 21:04
  • Indeed, it does; generally, editing new code into the one's question or answer is used for that reason. BTW, I used `<` in the comparison just in case we had an impossible date -- something like 2014-01-40 -- in our `endDate` field; if that were to happen, `!=` would always be true, even after we went on past to 2014-02-01 and onward; since YYYY-MM-DD is a lexically sorting date format (good choice!), it can just be compared as a string. – Charles Duffy Oct 18 '14 at 21:36
  • yes, but had to alter the argument as `while [[ $day != $(date -d "$lastDay + 1 days" +%Y%m%d) ]]; do` or I wouldn't catch the last day of month only the day before (30th of oct.) – Christofer Andersson Oct 19 '14 at 08:19
  • Good point; I changed it from `<` to `<=` for that reason (more efficient than running a `date` command in a subshell to calculate `lastDay + 1 days` every time through the loop, and avoids the endless-loop-on-invalid-dates issue described earlier). – Charles Duffy Oct 19 '14 at 16:40