ubuntuusers.de

Bash, AWK. Die txt Datei überschreiben, nicht hinten einfügen.

Status: Ungelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

Kilowatt

Anmeldungsdatum:
4. Dezember 2017

Beiträge: Zähle...

Wohnort: Salzgitter

Ich glaube es ist eine ganz einfache Frage auf die ich trotz 6 stunden Suche keine Antwort gefunden habe. Es soll einfach die Ausgabedatei alle 10 Sekunden mit neuen Daten überschrieben werden, statt hinten anzufügen. Das ist alles. Mit > >> größer als hat nicht geklappt, die Daten werden trotzdem unten eingefügt.

1
2
3
4
5
6
#!/bin/bash
stty -F /dev/ttyUSB0  19200
sed -u '/Typ/,/Messzeit/d; /^A-Z/d; /^[ \t]*$/d; /\x00/d; s/,/./g' /dev/ttyUSB0 | awk '{OFS=",";$3+=0.9;$5+=3;$10+=1;$1=$2;$2=$3;$3=$4;$4=$5;$5=$6;
$6=$7;$7=$8;$8=$9;$9=$10;$10=$11;$11=$12;$12=$13;$13=$14;$14=$15;$15=$16;$16=$17;$17=$18;$18=$19;$19=$20;
$18/=10;$19=$19=($18*60*1.16)*($2-$3);$19=sprintf("%.0f",$19);$20=sprintf("%.2f",$19/365);
print strftime("%Y/%m/%d--%H:%M:%S"",")$0;fflush()}' > /mnt/ramdisk/usb.log
2024/10/29--22:22:19,033.0,35.5,030.3,20.2,010.3,013.4,051.8,034.5,13.8,050,050,099,030,111,166145153,024223160,4.5,23,8324,22.81
2024/10/29--22:22:29,033.0,35.5,030.4,20.2,010.3,013.4,051.8,034.5,13.9,050,050,099,030,111,166145173,024223165,4.6,23,8164,22.37
2024/10/29--22:22:39,033.0,35.5,030.4,20.2,010.3,013.4,051.8,034.5,13.8,050,050,099,030,111,166145193,024223170,4.5,23,8164,22.37
2024/10/29--22:22:48,033.0,35.5,030.4,20.2,010.3,013.4,051.8,034.5,13.7,050,050,099,030,111,166145213,024223175,4.6,23,8164,22.37
2024/10/29--22:22:58,033.0,35.5,030.4,20.2,010.3,012.8,051.8,034.5,13.9,050,050,099,030,111,166145233,024223180,4.7,23.2,8235,22.56
2024/10/29--22:23:07,033.0,35.5,030.4,20.2,010.4,012.6,051.8,034.5,14,050,050,099,030,111,166145253,024223180,4.7,23.2,8235,22.56
2024/10/29--22:23:17,033.0,35.5,030.4,20.2,010.4,012.6,051.8,034.5,13.9,050,050,099,030,111,166145268,024223185,4.5,23,8164,22.37

Es soll nur eine letzte Zeile zu sehen sein.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13131

In der Shell musst Du eine neue Umleitung haben - anders geht es nicht:

1
2
3
while sleep 1; do
  date > /mnt/ramdisk/usb.log
done

Zur Verdeutlichung, dass ich absichtlich kürzen will, nehme ich üblicherweise >| statt >. Das hat auch den Vorteil, dass die Shell im noclobber Modus (set -C) auch dann die Datei überschreibt. Dann sieht das so aus:

1
2
3
while sleep 1; do
  date >| /mnt/ramdisk/usb.log
done

Kilowatt

(Themenstarter)

Anmeldungsdatum:
4. Dezember 2017

Beiträge: 63

Wohnort: Salzgitter

Danke für Deine Hilfe, irgendwie kriege ich es nicht hin. Egal was ich mache, entweder kommen gar keine Daten, oder es wird unten eingefügt.

bash: /home/pi/usb.log: Das Programm kann nicht ausgeführt oder verändert werden (busy)
^C
pi@raspberrypi:~ $ #!/bin/bash
stty -F /dev/ttyUSB0  19200
sed -u '/Typ/,/Messzeit/d; /^A-Z/d; /^[ \t]*$/d; /\x00/d; s/,/./g' /dev/ttyUSB0 | awk '{OFS=",";$3+=0.9;$5+=3;$10+=1;$1=$2;$2=$3;$3=$4;$4=$5;$5=$6;
$6=$7;$7=$8;$8=$9;$9=$10;$10=$11;$11=$12;$12=$13;$13=$14;$14=$15;$15=$16;$16=$17;$17=$18;$18=$19;$19=$20;
$18/=10;$19=$19=($18*60*1.16)*($2-$3);$19=sprintf("%.0f",$19);$20=sprintf("%.2f",$19/365);
print strftime("%Y/%m/%d--%H:%M:%S"",")$0;fflush()}'
while sleep 1; do
 date >| /home/pi/usb.log
done
2024/10/30--16:54:37,3.,2.9,1.,3,1.,4.,3.,1.,6,5,9,3,1,6179,2250,48028050,,0,0,0.00
2024/10/30--16:54:47,3.0150740720940.,4.9,3.,4,5,5,9,3,2,6171,2250,48020050,,,,,,0,0,0.00
^C
^C
pi@raspberrypi:~ $ #!/bin/bash
stty -F /dev/ttyUSB0  19200
sed -u '/Typ/,/Messzeit/d; /^A-Z/d; /^[ \t]*$/d; /\x00/d; s/,/./g' /dev/ttyUSB0 | awk '{OFS=",";$3+=0.9;$5+=3;$10+=1;$1=$2;$2=$3;$3=$4;$4=$5;$5=$6;
$6=$7;$7=$8;$8=$9;$9=$10;$10=$11;$11=$12;$12=$13;$13=$14;$14=$15;$15=$16;$16=$17;$17=$18;$18=$19;$19=$20;
$18/=10;$19=$19=($18*60*1.16)*($2-$3);$19=sprintf("%.0f",$19);$20=sprintf("%.2f",$19/365);
print strftime("%Y/%m/%d--%H:%M:%S"",")$0;fflush()}'
while sleep 1; do
     >| /home/pi/usb.log
done
2024/10/30--16:56:13,.,3.9,85,3,,,,,1,,,,,,,,,0,-0,-0.00
2024/10/30--16:56:23,2.,1.9,0.,4,4..,1.,5,5,10,3,1,6180,2254,48020010,,,,0,0,0.00
2024/10/30--16:56:32,3.,1.9,5,8,9,3,1,61004270,1,03,85,,,,,,,0,-0,-0.00
^C
^C
pi@raspberrypi:~ $ #!/bin/bash
stty -F /dev/ttyUSB0  19200
sed -u '/Typ/,/Messzeit/d; /^A-Z/d; /^[ \t]*$/d; /\x00/d; s/,/./g' /dev/ttyUSB0 | awk '{OFS=",";$3+=0.9;$5+=3;$10+=1;$1=$2;$2=$3;$3=$4;$4=$5;$5=$6;
$6=$7;$7=$8;$8=$9;$9=$10;$10=$11;$11=$12;$12=$13;$13=$14;$14=$15;$15=$16;$16=$17;$17=$18;$18=$19;$19=$20;
$18/=10;$19=$19=($18*60*1.16)*($2-$3);$19=sprintf("%.0f",$19);$20=sprintf("%.2f",$19/365);
print strftime("%Y/%m/%d--%H:%M:%S"",")$0;fflush()}'
while sleep 1; do
     >| /home/pi/usb.log
done
2024/10/30--16:58:27,033.0,32.6,027.5,20.2,009.5,012.4,048.4,031.8,13.7,050,050,099,030,111,166158350,024225795,4.8,22.8,8093,22.17
^C
^C
pi@raspberrypi:~ $ 

juribel

Anmeldungsdatum:
20. April 2014

Beiträge: 1232

Hast du schon mal darüber nachgedacht, das Ganze nicht mit so einem Einzeiler-Monstrum aus sed, awk und bash zu machen, sondern in einer Programmiersprache, die für so etwas gemacht ist, z. B. Perl? Und vor allem in kleinen Häppchen, die du für sich verändern und testen kannst, und die du auch in vier Wochen noch verstehst? Schreibe beim Programmieren keine Zeilen, die länger sind als 80-100 Zeichen und verwende reichlich Kommentare.

shiro

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1214

Hallo Kilowatt,

ehrlich gesagt verstehe ich nicht so ganz, was du wirklich machen willst. Ich hätte erwartet, dass du folgendes schreibst:

stty -F /dev/ttyUSB0  19200
sed -u '/Typ/,/Messzeit/d; /^A-Z/d; /^[ \t]*$/d; /\x00/d; s/,/./g' /dev/ttyUSB0 | 
awk '{OFS=",";$3+=0.9;$5+=3;$10+=1;$1="";$19/=10;
$20=sprintf("%.0f",($19*60*1.16)*($3-$4));$21=sprintf("%.2f",$20/365);
print strftime("%Y/%m/%d--%H:%M:%S")$0}' | 
while read line; do echo "$line" >/mnt/ramdisk/usb.log; done

Nach dem unbuffered "sed" ist meiner Meinung nach der "fflush()" im "awk" eigentlich nicht erforderlich. So wie ich dich verstanden haben, willst du nur die letzte Ausgabe der "awk" Statements in der Datei haben. Was du mit dem "awk" aber geschrieben hast sorgt dafür, das alle Werte in die Datei geschrieben werden.

Eine kleine Änderung in der "awk" Zeile habe ich noch gemacht. Du musst nicht alle Felder um eine Position nach unten verschieben. Es reicht, wenn du das erste Feld löschst und das damit vorhandene führende Komma bei $0 im "strftime" dir sparst.

Kilowatt

(Themenstarter)

Anmeldungsdatum:
4. Dezember 2017

Beiträge: 63

Wohnort: Salzgitter

@juribel und @shiro Danke für ihre Antworten. Es geht um datenloggen, auswerten und visualisieren einer L/W Wärmepumpe. Dieser Script wurde 2017 mit Hilfe von @track, @seahawk1986, @rklm erstellt und läuft bis heute einwandfrei. Link: https://forum.ubuntuusers.de/topic/doppelte-datum-eintraege-in-log-datei/ Link: https://forum.ubuntuusers.de/topic/die-log-zeile-spaltenweise-in-einzelne-variabl/ Der Grund wieso ich die Datei überschrieben haben möchte, mir läuft RAM Speicher voll. Davor habe ich auf eine SD Karte geschrieben. Da mir in diesen Jahren durch die ständige Schreibzugriffe 3 SD Karten kaputt gegangen sind, lass ich jetzt die Daten in den RAM schreiben, die dann in der Visualisierung dargestellt werden und von da in einen Datenbank kopiert werden. @shiro Danke!! Habe eben von Dir überarbeiteten Skript ausprobiert, funktioniert 1A. Allerdings ohne fflush() kam nur Müll raus, erst nachdem ich fflush() wieder eingefügt habe, kamen ordentliche Daten. So sieht es aus:

Bilder

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13131

Mein Code war lediglich ein Beispiel für das Überschreiben. date brauchst Du nicht.

Du musst die Datei immer öffnen und schließen. Das geht übrigens auch in awk. Wieder ein Beispiel, das Du für Deinen Fall anpassen musst:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$ for i in {0..20}; do echo $i; sleep 1; done | awk '{print ">>>" $0 > "log"; close("log")}' &
$ cat log
>>>6
$ cat log
>>>7
$ cat log
>>>8
$ cat log
>>>9
$ cat log
>>>9
$ cat log
>>>9
$ cat log
>>>10
$ cat log
>>>10
$ cat log
>>>11
$ cat log
>>>11

Das Entscheidende ist die Ausgabeumleitung im awk-Skript und der close().

Antworten |