ubuntuusers.de

Mit sed mehrere Teile eines Strings mehreren Variablen zuordnen

Status: Gelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

JörgZ

Anmeldungsdatum:
6. Juli 2009

Beiträge: Zähle...

Hallo, folgendes Problem, dass ich nicht gelöst bekomme. Ich habe durch einen Programmaufruf eine Ergebniszeile auf stdout die sieht so aus:

1
RESULT = {"LedPower":"OFF"}

oder allgemein

1
RESULT = {"ITEM":"VALUE"}

Ich möchte nun im Rahmen eines Shell-Skriptes den Inhalt von ITEM in einer Variablen $a haben und den Inhalt von VALUE in einer Variablen $b. Der Rest (also RESULT = {" und ":" und "}) interessiert nicht und sind immer gleich. Mit $a und $b will ich dann in meinem Skript weiterarbeiten. Mangels ausreichender Kenntnis und Erfahrung mit sed bekomme ich es nicht hin. Zudem lese ich nicht Dateien ein sondern möchte immer wieder einen (stdout-) Output weiterverarbeiten. Kann mir jemand helfen. Das sind für sed-Profis vermutlich peanuts. Danke!

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

wenn ich Dich recht verstehe, willst Du offenbar mit einem Befehl mehrere Variablen zugleich zuweisen ?

Das geht in der Shell so nicht, und auch die Syntax hast Du wohl irgendwoher, nur nicht von der Shell ... 😉
Vielleicht solltest Du mal in unser Wiki gucken  ?
Aansonsten ... mal der Reihe nach:

  1. Variablenzuweisungen stehen bei der Shell immer ohne Leerzeichen, sonst zerkloppt die Shell sie in mehrere Token.

  2. Mehrfachzuweisungen sind nur im Rahmen von Arrays möglich. Dann aber mit (runden Klammern) und dem Leerzeichen als Trenner, und nicht mit {geschweiften}, und auch nicht mit Doppelpunkten.

  3. Eigene Variablen solltest Du $klein schreiben, denn $GROSS ist für Systemvariablen reserviert, und Du möchtest sicherlich nicht aus Versehen Deine Systemkonfiguration kaputt schreiben ... 😀

Insgesamt könnte es also sowas werden:

schalter=(EIN AUS EIN EIN AUS AUS)
echo "Schalter 4 ist ${schalter[4]}"         # wobei Schalter 4 jetzt z.B. die PowerLed sein könnte

Oder Du nimmst assoziative Arrays, dann kannst Du auch Namen als Index vergeben. (Nur musst Du die dann einzeln zuweisen ...)

Das so mal als Grobskizze.

LG,

track

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13204

Ich finde das ja immer spannend so etwas mit Bordmitteln der POSIX-Shell zu lösen. Hier ist ein Weg:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ set -x
$ input='RESULT = {"LedPower":"OFF"}'
+ input='RESULT = {"LedPower":"OFF"}'
$ a="${input#*\"}"
+ a='LedPower":"OFF"}'
$ b="${a#*:}"
+ b='"OFF"}'
$ a="${a%%\"*}"
+ a=LedPower
$ b="${b#*\"}"
+ b='OFF"}'
$ b="${b%\"*}"
+ b=OFF
$ echo "a=$a b=$b"
+ echo 'a=LedPower b=OFF'
a=LedPower b=OFF

Hier etwas strukturierter:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ a="${input%%:*}"
+ a='RESULT = {"LedPower"'
$ a="${a#*\"}"
+ a='LedPower"'
$ a="${a%\"*}"
+ a=LedPower
$ b="${input##*:}"
+ b='"OFF"}'
$ b="${b#*\"}"
+ b='OFF"}'
$ b="${b%\"*}"
+ b=OFF
$ echo "a=$a b=$b"
+ echo 'a=LedPower b=OFF'
a=LedPower b=OFF

So richtig klassisch mit expr sähe das so aus:

1
2
3
4
5
6
7
8
9
$ a=$(expr "$input" : '.*{"\([^"]*\)"')
++ expr 'RESULT = {"LedPower":"OFF"}' : '.*{"\([^"]*\)"'
+ a=LedPower
$ b=$(expr "$input" : '.*{"[^"]*":"\([^"]*\)"')
++ expr 'RESULT = {"LedPower":"OFF"}' : '.*{"[^"]*":"\([^"]*\)"'
+ b=OFF
$ echo "a=$a b=$b"
+ echo 'a=LedPower b=OFF'
a=LedPower b=OFF

Natürlich kann man das auch mit sed bauen, aber das finde ich hier uneleganter, weil man dafür zwei Prozesse braucht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ a=$(echo "$input" | sed 's#.*{"\([^"]*\)".*#\1#')
++ echo 'RESULT = {"LedPower":"OFF"}'
++ sed 's#.*{"\([^"]*\)".*#\1#'
+ a=LedPower
$ b=$(echo "$input" | sed 's#.*{"[^"]*":"\([^"]*\)".*#\1#')
++ echo 'RESULT = {"LedPower":"OFF"}'
++ sed 's#.*{"[^"]*":"\([^"]*\)".*#\1#'
+ b=OFF
$ echo "a=$a b=$b"
+ echo 'a=LedPower b=OFF'
a=LedPower b=OFF

Such Dir was aus. ☺

TausB

Avatar von TausB

Anmeldungsdatum:
26. November 2009

Beiträge: 1570

Wohnort: Terra incognita

Wie wäre es damit?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash

input='RESULT = {"LedPower":"OFF"}'
input=${input//\RESULT = \{\"}
input=${input//\":\"/ }
input=${input//\"\}/}

input=($input)
a="${input[0]}"
b="${input[1]}"

echo $a und $

Also ein Array daraus basteln. ☺

EDIT: Musste noch einen kl. Fehler korrigieren ...

JörgZ

(Themenstarter)

Anmeldungsdatum:
6. Juli 2009

Beiträge: 17

@TausB und @rklm:

Herzlichen Dank für die schnelle Lösung! Ich habe zunächst einmal den Vorschlag von TausB übernommen und in mein Rahmenskript eingebaut, und es hat funktioniert. Was ich besonders gut fand: Es kommt ohne sed aus, was alles in der Tat übersichtlicher macht. Wie du die überflüssigen Inhalte weggedrückt hast, muss ich mir allerdings noch einmal genauer ansehen. Und dadurch dass die relevanten Werte in einem Array abgelegt sind, ergeben sich noch weitere Möglichkeiten alles in einer Schleife abzuarbeiten. Das wird sich sicher noch auf andere Skripte auswirken.

Antworten |