[gelöst] Werte in Array schreiben

Started by bluelupo, 2014/11/06, 21:33:54

Previous topic - Next topic

bluelupo

Hallo zusammen,
ich bin auf der Fehlersuche in diesem Shellscript. Leider komm ich nicht drauf ;-)

Aufruf: ./run_onlinetime.sh -s "2014-11-01 00:00:00" -u "2014-11-02 23:59:59"
Option -s ($SINCE )
Option -u ($UNTIL)


do_create_timestamps()
{
   # In Array Index, Datum, Zeit und absoluten Sekundenwert der Onlinezeiten schreiben
   journalctl --since="$SINCE" --until="$UNTIL" --output=short-iso --no-pager | egrep '(command line: BOOT_IMAGE|Journal stopped)' | while read JOURNAL_ROW
      do
      # ersten Wert ueberspringen wenn dieser den Wert "Journal stopped" enthält
      SKIP=`expr match "$JOURNAL_ROW" '.*Journal stopped'`
     if [ $INDEX -eq 0 -a $SKIP -ne 0 ]
        then
        continue
     fi
      TS=$(echo $JOURNAL_ROW | cut -d" " -f1|awk -F"T" '{print $1"#"$2}' | awk -F"+" '{print $1}')
      TMP=$(echo ${TS//#/ })
      TIME_IN_SEC=$(date --utc --date "$TMP" +%s)
      #echo "$INDEX"#"$TS"#"$TIME_IN_SEC"
      ARRAY_TIMESTAMP[$INDEX]=$INDEX"#"$TS"#"$TIME_IN_SEC
      INDEX=$(($INDEX + 1))
   done

for X in ${ARRAY_TIMESTAMP[@]}
   do
   echo $X
done

#Werte ausgeben
echo "Werte:"${#ARRAY_TIMESTAMP[@]}

# Anzahl der Zeilen ausgeben
echo "Anzahl der Werte:"${ARRAY_TIMESTAMP[0]}
}


Ausgabe des Scripts:

Werte:
Anzahl der Werte:0


Leider wird hier nichts in das Array "ARRAY_TIMESTAMP" geschrieben und deshalb kann auch nichts ausgegeben werden. Wieso klappt das nicht?

Kommentiere ich hingegen die Zeile ein..

echo "$INDEX"#"$TS"#"$TIME_IN_SEC"

...so werden Werte ausgegeben aber das Array ist natürlich immer noch leer. Hmmm!

Ausgabe:

0#2014-11-01#22:18:46#1414880326
1#2014-11-02#17:49:00#1414950540
2#2014-11-02#17:53:31#1414950811
3#2014-11-02#17:53:54#1414950834
4#2014-11-02#21:54:52#1414965292
Werte:
Anzahl der Werte:0


Die Zuweisung der Werte ins Array dürfte wohl fehlerhaft sein - aber ich komm nicht drauf wo der Fehler steckt.
ARRAY_TIMESTAMP[$INDEX]=$INDEX"#"$TS"#"$TIME_IN_SEC

bluelupo

Ich gebe mir selbst eine Antwort, da ich das Scriptproblem gelöst habe. Evtl. ist das für euch interessant wo die Probleme lagen.

Die Problematik lag bei der internen Bash-Variable IFS (internal field separator). IFS erkennt Felder- oder Wortgrenzen in der Bash.

So sieht die Funktion jetzt aus.

[...]
do_create_timestamps()
{
# Ausgabe aus dem Journal aufbereiten. Letzter awk-Befehl mit #-Trennzeichen aufbereitet, da sonst die einzelnen Spalten untereinander ausgegeben werden
for TS in $(journalctl --since="$SINCE" --until="$UNTIL" --output=short-iso --no-pager | egrep '(Kernel command line|Shutting down)' | cut -d" " -f1,4,5 | awk -F"T" '{print $1,$2}' | sed -e 's/+[0-9]\{4\}//' -e 's/\.//' | awk '{printf("%s#%s#%s%s\n",$1,$2,$3,$4)}')
do
# Wenn der erste Eintrag ein Shuttingdown ist, gehe zum nächsten Eintrag
SKIP=`expr match "$TS" '.*Shuttingdown'`
if [ $INDEX -eq 0 -a $SKIP -ne 0 ]
then
continue
fi
# einzelne Felder erzeugen und dem Array hinzufuegen
DATE=$(echo $TS | cut -d"#" -f1)
TIME=$(echo $TS | cut -d"#" -f2)
TMP=$(echo $TS | awk -F"#" '{print $1,$2}')
TIME_IN_SEC=$(date --utc --date "$TMP" +%s)
TRIGGER=$(echo $TS | cut -d"#" -f3)
ARRAY_TIMESTAMP[$INDEX]=$INDEX"#"$DATE"#"$TIME"#"$TIME_IN_SEC"#"$TRIGGER
INDEX=$(( $INDEX + 1 ))
done
}
[...]


Das Array wird dann so ausgegeben wie ich es haben will. Spaltentrenner ist der "#" mit den Feldern Index, Datum, Uhrzeit, Zeit in Sekunden seit dem 1.1.1970, Trigger für Hochfahren bzw. Herunterfahren und die Differenz-Zeiten zwischen Hoch- und Runterfahren des PC.

for ROW in ${ARRAY_TIMESTAMP[@]}
   do
   echo $ROW
done

0#2014-11-02#17:49:00#1414950540#Kernelcommand#0
1#2014-11-02#17:53:31#1414950811#Shuttingdown#271
2#2014-11-02#17:53:54#1414950834#Kernelcommand#0
3#2014-11-02#21:54:52#1414965292#Shuttingdown#14458


Der Knackpunkt liegt in der FOR-Schleife beim awk-Kommando, der mit den Feldtrenner "#" versehen werden muss ansonsten erfolgt ein falscher Zeilenumbruch und das Array wird nicht richtig aufgebaut (Spaltertrenner ist diesem Fall das Leerzeichen).


awk '{printf("%s#%s#%s%s\n",$1,$2,$3,$4)}'