chris159
Anmeldungsdatum: 15. September 2020
Beiträge: Zähle...
|
ich ersuche um Hilfe/Unterstützung bei folgender Aufgabe mit positiven Temperatur-Messwerten in einem String.
Sämtliche Versuche mit sed, awk, grep, cut scheitern leider bisher. Aus folgendem String z.b.:
22.62525.062522.687522.687522.687522.562522.6875 soll mittels sed, awk..
[22.625,25.0625,22.6875,22.6875,22.6875,22.5625,22.6875]
werden. Ideal wäre die Begrenzung auf 1 Nachkommastelle:
[22.6,25.0,22.6,22.6,22.6,22.5,22.6] D.h. in der 1. Stufe alle "." suchen,
dann 2 Zeichen vor jedem "." und 1 Zeichen nach jedem "." nehmen, mit "," jeweils trennen und für die ganze Zeile anwenden. Danke für Eure Mühe!
|
Doc_Symbiosis
Anmeldungsdatum: 11. Oktober 2006
Beiträge: 4378
Wohnort: Göttingen
|
Hm, kannst Du da bei der Anlieferung der Daten nicht etwas drehen? So die Daten auseinanderzupflücken is doch ziemlich umständlich... EDIT:
In Perl ginge es, schnell zusammengezimmert mal so:
#!/usr/bin/env perl
use strict;
use warnings;
my $var="22.62525.062522.687522.687522.687522.562522.6875";
print "[";
while ($var ne "")
{
$var=~ m/([0-9][0-9]\.[0-9])(.*)/;
print "$1";
if (index($2, ".") != -1) {
print ",";
$var=$2;
} else {
$var="";
}
}
print "]"; Ein Perl-Spezi bekommt das sicherlich noch erheblich schöner und kürzer hin...
|
MisterIgo
Anmeldungsdatum: 23. April 2009
Beiträge: 947
|
Das geht auch (zumindest für den Test):
$ echo '22.62525.062522.687522.687522.687522.562522.6875' | sed -E 's/([0-9][0-9]\.[0-9])/ \1 /g;s/ [0-9]+($| )/,/g;s/^ +/[/;s/,+$/]/'
[22.6,25.0,22.6,22.6,22.6,22.5,22.6]
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
chris159 schrieb: Aus folgendem String z.b.:
22.62525.062522.687522.687522.687522.562522.6875 soll mittels sed, awk..
[22.625,25.0625,22.6875,22.6875,22.6875,22.5625,22.6875]
werden. Ideal wäre die Begrenzung auf 1 Nachkommastelle:
[22.6,25.0,22.6,22.6,22.6,22.5,22.6] D.h. in der 1. Stufe alle "." suchen,
dann 2 Zeichen vor jedem "." und 1 Zeichen nach jedem "." nehmen, mit "," jeweils trennen und für die ganze Zeile anwenden.
Also reicht doch eigentlich sowas:
$ grep -Po "\d\d\.\d" <<< '22.62525.062522.687522.687522.687522.562522.6875'
22.6
25.0
22.6
22.6
22.6
22.5
22.6
$ grep -Po "\d\d\.\d" <<< '22.62525.062522.687522.687522.687522.562522.6875' | paste -sd ',' -
22.6,25.0,22.6,22.6,22.6,22.5,22.6
$ echo "[$(grep -Po "\d\d\.\d" <<< '22.62525.062522.687522.687522.687522.562522.6875' | paste -sd ',' -)]"
[22.6,25.0,22.6,22.6,22.6,22.5,22.6]
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
Ich habe gerade keine Shell zum testen, aber so würde ich das angehen: | echo '22.62525.062522.687522.687522.687522.562522.6875' | sed -re 's#(\.[0-9]{2})[0-9]+#\1#;s#^#[#;s#$#]#'
|
Edit: sehe gerade, ich habe da was falsch gelesen. Diese Lösung funktioniert nicht.
|
chris159
(Themenstarter)
Anmeldungsdatum: 15. September 2020
Beiträge: 6
|
Danke an die Experten!
Die Lösung von MisterIgo ist für mich am Nützlichsten ☺
Sollten sich "85.0" Temperaturmessfehler (DS18B20 Sensor) ergeben, würde ich diese gerne mit "xx.x" ersetzen, also via pipe sed -e ":a;s/85.0/xx.x/;ta" Ich denke das passt so....
|
Doc_Symbiosis
Anmeldungsdatum: 11. Oktober 2006
Beiträge: 4378
Wohnort: Göttingen
|
Echt? Ich finde ja die Lösung von Seahawk hervorragend, so schön schlicht...
Aber ganz nimm natürlich das, was deinen Anforderungen am Besten entspricht. Falls das Problem damit für Dich erledigt ist, markiere das Thema bitte noch als gelöst.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
Meine Variante von Misterlogos: | $ echo '22.62525.062522.687522.687522.687522.562522.6875' | sed -re 's#[0-9]{2}\.# &#g;s#(\.[0-9])[0-9]* ?#\1,#g;s#^ *#[#;s#,?$#]#'
[22.6,25.0,22.6,22.6,22.6,22.5,22.6]
|
Insgesamt muss man allerdings sagen, dass das nur verlässlich funktioniert, wenn entweder die Anzahl der Stellen vor oder nach dem Dezimaltrenner fix sind. Keine Maschinenintelligenz kann ohne weitere Eingabe berechnen, ob man "22.62525" auftrennt in "22.625" und "25" oder "22.6" und "2525". Ich finde das Datenformat fragil. Wenn die Regex-Engine Lookahead hat, dann kann man auch diesen Ansatz verfolgen: | $ ruby -e 'p "22.62525.062522.687522.687522.687522.562522.6875".scan(/\d+\.\d+(?:(?=\d\d|$))/)'
["22.625", "25.0625", "22.6875", "22.6875", "22.6875", "22.5625", "22.6875"]
$ ruby -e 'puts "[" << "22.62525.062522.687522.687522.687522.562522.6875".scan(/\d+\.\d+(?:(?=\d\d|$))/).map {|s|s[/\A\d+\.\d/]}.join(",")<<"]"'
[22.6,25.0,22.6,22.6,22.6,22.5,22.6]
|
|
MisterIgo
Anmeldungsdatum: 23. April 2009
Beiträge: 947
|
rklm schrieb: Meine Variante von Misterlogos: | $ echo '22.62525.062522.687522.687522.687522.562522.6875' | sed -re 's#[0-9]{2}\.# &#g;s#(\.[0-9])[0-9]* ?#\1,#g;s#^ *#[#;s#,?$#]#'
[22.6,25.0,22.6,22.6,22.6,22.5,22.6]
|
Das ist besser, da es das initiale Pattern von "ZahlZahl.Zahl" auf "ZahlZahl." reduziert.
Fragil bleibt das natürlich trotzdem alles. Gibt es in der Eingabe auch dreistellige Zahlen? Haben immer alle Zahlen ein Komma (bzw. Punkt)? (Und ich habe wieder ein bisschen was über sed-Regexes gelernt, danke ☺ )
|
chris159
(Themenstarter)
Anmeldungsdatum: 15. September 2020
Beiträge: 6
|
In der Eingabe gibt es keine dreistellige Zahlen. Alle Zahlen haben immer einen Punkt. Wenn auch die Aussentemperatur zum Einsatz kommt, wären auch einstellige bzw. negative Zahlen zu berücksichtigen. Eine Stelle nach dem Komma bzw. Punkt bleibt jedenfalls fix. Danke! MisterIgo schrieb: rklm schrieb: Meine Variante von Misterlogos: | $ echo '22.62525.062522.687522.687522.687522.562522.6875' | sed -re 's#[0-9]{2}\.# &#g;s#(\.[0-9])[0-9]* ?#\1,#g;s#^ *#[#;s#,?$#]#'
[22.6,25.0,22.6,22.6,22.6,22.5,22.6]
|
Das ist besser, da es das initiale Pattern von "ZahlZahl.Zahl" auf "ZahlZahl." reduziert.
Fragil bleibt das natürlich trotzdem alles. Gibt es in der Eingabe auch dreistellige Zahlen? Haben immer alle Zahlen ein Komma (bzw. Punkt)? (Und ich habe wieder ein bisschen was über sed-Regexes gelernt, danke ☺ )
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
Ganz ehrlich, das Format ist totaler Mist. Wo kommt das her? Kannst Du das nicht ändern?
|
chris159
(Themenstarter)
Anmeldungsdatum: 15. September 2020
Beiträge: 6
|
rklm schrieb: Ganz ehrlich, das Format ist totaler Mist. Wo kommt das her? Kannst Du das nicht ändern?
Ja, stimmt, das Format ist Mist!
Ich erhalte es mittels OWFS und der Temperaturabfrage via "cat /tmp/1wire/28*/temperature"
Leider muss ich festellen, dass auch Werte ohne Komma bzw. Punkt auftauchen, z.b. 23 °C.
Dann funktioniert der sed-Befehl schon nicht mehr richtig, nämlich: cat /tmp/1wire/28*/temperature
2325.687523.062523.062523.062522.937523 mit sed:
[23 25.6,23.0,23.0,23.0,22.9,23.0] Habt' Ihr eine Idee, wie ich den String zur besseren Bearbeitung in Form bringen kann?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
chris159 schrieb: Temperaturabfrage via "cat /tmp/1wire/28*/temperature"
Habt' Ihr eine Idee, wie ich den String zur besseren Bearbeitung in Form bringen kann?
Kann es sein, dass du da mehrere Sensoren auf einmal ausliest, weil die Wildcard für mehr als ein Verzeichnis gilt?
Dann wäre die Lösung einfach:
echo "[$(paste -d ',' /tmp/1wire/28*/temperature)]"
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Zur Erklärung: wenn OWFS die Werte in Dateien ohne Zeilenumbruch am Ende darstellt, kopiert cat die einfach ohne Trenner zusammen - in dem Fall ist paste besser, weil es die aus den einzelnen Dateien gelesenen Daten sinnvoll verketten kann.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12802
|
seahawk1986 schrieb: Zur Erklärung: wenn OWFS die Werte in Dateien ohne Zeilenumbruch am Ende darstellt, kopiert cat die einfach ohne Trenner zusammen - in dem Fall ist paste besser, weil es die aus den einzelnen Dateien gelesenen Daten sinnvoll verketten kann.
sed würde auch tun: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | $ od -t x1c x*
0000000 61 61 62 62
a a b b
0000004
$ od -t x1c x1
0000000 61 61
a a
0000002
$ od -t x1c x2
0000000 62 62
b b
0000002
$ cat x*
aabb$
$ sed 's#$##' x*
aa
bb$
$ paste -s x*
aa
bb
|
Aber klar, die Werte sollte man besser einzeln auslesen. Oder halt paste .
|