ubuntuusers.de

Bash script um variablen in log datei zu schreiben

Status: Ungelöst | Ubuntu-Version: Ubuntu 20.04 (Focal Fossa)
Antworten |

thiago10

Anmeldungsdatum:
23. April 2022

Beiträge: Zähle...

Hallo, ich habe erst neulich mit bash Programmierung angefangen und komme leider nicht mehr weiter.

Ich möchte eine Variable, die bei der CFD Simulation in eine log Datei gespeichert ist, automatisiert durch ein bash skript in eine separate Datei schreiben. Das Bash Skript soll diese Variable für jeden Durchlauf mit der zugehörigen Zeit auflisten, sodass ich diese Variable über die Zeit beispielsweise mit Excel danach plotten kann.

Wie geht man hierbei vor?

Im Anhang ist ein code den ich im Internet gefunden habe. Leider funktioniert das nicht. Im Anhang habe ich die Fehlermeldung beigefügt.

Ich hoffe jemand kann mir dabei helfen ☺

Bilder

Doc_Symbiosis

Avatar von Doc_Symbiosis

Anmeldungsdatum:
11. Oktober 2006

Beiträge: 4453

Wohnort: Göttingen

Hallo,

willkommen hier im Forum! Bitte verwende keine Screenshots, sondern poste die Ausgaben in Codelöcken, siehe Forum/Syntax (Abschnitt „Syntaxelemente“).

shiro Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1269

Hallo thiago10,

Der Screenshot aus nano lässt vermuten, dass du einen Zeilenumbruch nach "s/^Time = " eingebaut hast. Dann erklärt sich die Fehlermeldung. Der sed Befehl macht folgendes:

  • Suche nach einer Zeile, die mit "Time = " beginnt

  • definiere das Sprungziel "a" (:a) und appende die gelesene Zeile in den Puffer (N)

  • mache das so lange, bis der Text "Liquid penetration" irgendwo in der Zeile gefunden wird. Wird der Text in der Zeile nicht gefunden, hüpfe zur Sprungmarke "a" (!ba).

  • Wechsele alle Zeilenumbrüche ("\n") in Tabs ("\t") und schreib den Puffer raus (gp).

  • Danach wird die ausgegebene Zeile nachbearbeitet und eine wiss. Zahl (z.B. -1.23e4) nach "Time = " und "Liquid penetration" gesucht und ausgegeben (/\1 \2/).

  • Für eine Nachbearbeitung ist einer Tabellenkalkulation solltest du die Zahlen als csv Datei ausgeben mit (/\1;\2/)

Hier ein Beispiel:

echo -e "bla 1\nbla 2\nTime = 11.02.2021\nbla 3\nbla 4 Liquid pen 12.345\nbla 5\nTime = 12.02.2022\nBla 6\nLiquid pen 45.67e-2\nBla 7" | 
sed -n "/^Time = /{:a;N;/Liquid pen/!ba;s/\n/\t/gp}" | 
sed -n "s/^Time = \([-e\.0-9]\+\).*Liquid pen.* \([-e\.0-9]\+\)/\1;\2/p"

thiago10

(Themenstarter)

Anmeldungsdatum:
23. April 2022

Beiträge: 2

Hallo shiro,

vielen Dank für deine Hilfe. Du hattest recht, es lag am Zeilenumbruch.

Ich verstehe diesen Teil leider noch nicht: sed -n "s/^Time = \([-e\.0-9]\+\).*Liquid penetration.* = \([-e\.0-9]\+\)/\1 \2/p"

sed -n verhindert die Ausgabe des Ergebnisses. Wieso wird durch diesen Befehl trotzdem etwas ausgegeben, liegt das an dem "p" am Ende des Befehls? Für was steht das ".0-9]" in der Klammer? Wie lautet der Syntax für die Ausgabe einer wiss. Zahl?

Wie würde der Befehl für die Ausgabe einer csv Datei in meinem Fall konkret aussehen? Das Beispiel erzeugt aber keine csv Datei oder?

Ich habe leider keine Erfahrungen bei der Bash-Programmierung. Die Basics wie Schleifen, Arrays usw. verstehe ich zwar aber das Anwenden auf konkrete Problemstellungen fällt mir schwer. Hast du vielleicht eine Literaturempfehlung wie ich mir die Bash-Programmierung näher beibringen könnte?

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11260

Wohnort: München

thiago10 schrieb:

sed -n verhindert die Ausgabe des Ergebnisses. Wieso wird durch diesen Befehl trotzdem etwas ausgegeben, liegt das an dem "p" am Ende des Befehls?

Ja, p sorgt dafür, dass der pattern space ausgegeben wird, vgl. https://www.gnu.org/software/sed/manual/sed.html#sed-commands-list

Für was steht das ".0-9]" in der Klammer? Wie lautet der Syntax für die Ausgabe einer wiss. Zahl?

Du musst den kompletten Inhalt der Gruppe betrachten - \([-e\.0-9]\+\) sagt sed, dass es eine Abfolge von mindestens einem Zeichen aus den Zeichen -, e, . und den Ziffern von 0-9 suchen und sich merken soll. Das sind üblicherweise die Zeichen, mit denen Zahlen mit Zehnerpotenzen dargestellt werden.

Ich würde mir überlegen, ob man sich das Leben nicht leichter machen kann, wenn man das mit einer Skriptsprache wie Python3 angeht - Dinge wie ein brauchbarer Umgang mit CSV-Dateien sind da in der Standard Library schon drin (https://docs.python.org/3/library/csv.html) - und wenn man Daten plotten will, ist das mit matplotlib schnell erledigt.

Also z.B. grob:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/env python3
import csv
import fileinput
import sys

writer = csv.writer(sys.stdout)
for line in fileinput.input():
    if line.startswith('Time = '):
        _, date = line.split('Time = ')
    if 'Liquid penetration' in line:
        _, value = line.split('Liquid penetration')
        writer.writerow((date.strip(), value.strip()))

Das kann man dann so benutzen, wenn man das Skript ausführbar gemacht hat:

$ ./parse_CFD_log.py << EOF
bla 1
bla 2
Time = 11.02.2021
bla 3
bla 4 Liquid penetration 12.345
bla 5
Time = 12.02.2022
Bla 6
Liquid penetration 45.67e-2
Bla 7
EOF
11.02.2021,12.345
12.02.2022,45.67e-2

# bzw.
./parse_CFD_log.py log.txt > output.csv 

shiro Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1269

Hallo thiago10,

einen großen Teil deiner Fragen hat ja bereits seahawk1986 beantwortet.

Das von dir genutzte Script verwendet im Wesentlichen den "sed" Befehl. Die Bedeutung einiger Switches hast du ja bereits selbst heraus gefunden. Allerdings werden in dem Script einige "erweiterte" Funktionen (z.B. Schleifen und Nutzung div. Buffer) von sed verwendet weshalb ich dies Schritt für Schritt erläutert habe. Sed (aber auch andere Befehle/Sprachen) verwenden "reguläre Ausdrücke" (regex), die es einem ermöglichen komplexe Suchen durchzuführen und zu behandeln. Am Anfang wird man davon wenig verstehen. Hier lohnt es sich aber in die Materie einzuarbeiten.

Prinzipiell kannst du jede Programmieraufgabe mit den Werkzeugen lösen, die dir am besten gefallen. Dies kann z.B. die bash Shell mit den mächtigen Befehlen wie sed oder awk sein oder du verwendest eine Programmiersprache deiner Wahl (perl, ruby, js, java, python, C/C++ usw.).

Wie würde der Befehl für die Ausgabe einer csv Datei in meinem Fall konkret aussehen? Das Beispiel erzeugt aber keine csv Datei oder?

Doch, die Ausgabe mit dem Semikolon als Trennzeichen kann in eine csv Datei (z.B. ergebnis.csv) geleitet und von einem Tabellenkalkulationsprogramm (z.B. localc) geöffnet/weiterverarbeitet werden.

Obiges Beispiel modifiziert:

echo -e "bla 1\nbla 2\nTime = 11.02.2021\nbla 3\nbla 4 Liquid pen 12.345\nbla 5\nTime = 12.02.2022\nBla 6\nLiquid pen 45.67e-2\nBla 7" | 
sed -n '/^Time = /{:a;N;/Liquid pen/!ba;s/\n/\t/gp}' | 
sed -n "s/^Time = \([-e\.0-9]\+\).*Liquid pen.* \([-e\.0-9]\+\)/\1;\2/p" >ergebnis.csv
localc ergebnis.csv

Den ersten sed Befehl habe ich in ' und nicht in " eingefasst, damit das "!" Zeichen bei der interaktiven Nutzung keine Seiteneffekte (z.B. bash bang) verursacht. Bei "LibreOffice Calc" (localc) wirst du gefragt, wie die Daten zu interpretieren sind. Da die Zahlen mit Dezimal-Punkt eingetragen sind und im der deutschen Einstellung ein Dezimal-Komma verwendet wird, müsstest du bei localc beim Import die 2. Spalte mit den Zahlen auswählen und den Spaltentyp "Standard" in "US-Englisch" ändern, bevor du die Daten mit "OK" einliest.

Hast du vielleicht eine Literaturempfehlung wie ich mir die Bash-Programmierung näher beibringen könnte?

Hier sei auf das Scripting Guide für Anfänger dieses Web-Auftritts verwiesen. Als sehr gutes "Handbuch" ist das Advanced Bash-Scripting Guide zu empfehlen.

Antworten |