ZSH - splitting von Strings

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Liffi
Beiträge: 2345
Registriert: 02.10.2004 01:33:05

ZSH - splitting von Strings

Beitrag von Liffi » 28.07.2012 10:43:16

Ich versuche gerade ein Battery Plugin für oh-my-zsh zu schreiben, das mehrere Akkus unterstützt.

Mein Ziel ist es dabei nur auf Fähigkeiten der zsh zurückzugreifen, aber um mir das Leben nicht allzu sehr zu verkomplizieren, acpi benutze (und damit vermutlich einen ganzen Haufen Systeme ausschließe).

Code: Alles auswählen

all=$(acpi) 
# Beispiel für all:
# Battery 0: Full, 100%
# Battery 1: Charging, 90%, 00:21:49 until charged

all_as_array = ("${(s/%/)all}") # splitt all beim %
all_as_array[$#all_as_array]=() # remove the last (useless) element
...
Leider kommt bei mir beim Splitten nichts besonders sinnvolles raus:

Code: Alles auswählen

echo $all_as_array
# Battery 1: Charging, 90 , 00:21:49 until chargedBattery 0: Full, 100 
# Battery 1: Charging, 90 , 00:21:49 until charged

# erwartet hätte ich etwas in der Art:
# ( "Battery 0: Full, 100" "Battery 1: Charging, 90" ", 00:21:49 until charged")
Hat jemand eine Ahnung, was ich beim Splitten falsch mache?
Übersehe ich ein Sonderzeichen?

Zuerst wollte ich die Ausgabe von acpi zeilenweise durchgehen, aber es scheint doch kein richtiges newline zu geben.

EDIT:: Kommentar hinzugefügt.

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: ZSH - splitting von Strings

Beitrag von rendegast » 28.07.2012 17:06:32

(Ich habe nur eine Batterie, daher eine Zeilenverdopplung mit 'acpi | tee -')

Code: Alles auswählen

all=$(acpi | tee -)
echo $all
->
Battery 0: Discharging, 98%, discharging at zero rate - will never fully discharge. Battery 0: Discharging, 98%, discharging at zero rate - will never fully discharge.
Also einzeilig (bash), oder erhält zsh die Zeilenschaltung?

Code: Alles auswählen

all_as_array = ("${(s/%/)all}") # splitt all beim %
Das '(s/%/)' ist eine Art sed-Anweisung? Dann wäre das nur eine Entfernung der %.
Gewollt war vielleicht sowas '(s/%.*/)' (k.A.), also Entfernung des Zeilenrestes,
aber zeilenweise arbeitend?

Damit könntest Du das array gesteuerter aufbauen:

Code: Alles auswählen

acpi | tee - |
while read kind nr status charge rest; do
    echo K$kind N$nr S$status C$charge
done
->
KBattery N0: SDischarging, C98%,
KBattery N0: SDischarging, C98%,

Oder Du "filterst" das wieder über eine Variablenzuweisung, und die Ausgabe wird einzeilig:

Code: Alles auswählen

ausgabe=$(
acpi | tee - |
while read kind nr stat perc rest; do
    echo K$kind N$nr S$stat P$perc
done
)
echo Ausgabe $ausgabe
->
Ausgabe KBattery N0: SDischarging, P98%, KBattery N0: SDischarging, P98%,
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Liffi
Beiträge: 2345
Registriert: 02.10.2004 01:33:05

Re: ZSH - splitting von Strings

Beitrag von Liffi » 29.07.2012 12:53:04

rendegast hat geschrieben: Battery 0: Discharging, 98%, discharging at zero rate - will never fully discharge. Battery 0: Discharging, 98%, discharging at zero rate - will never fully discharge.
Also einzeilig (bash), oder erhält zsh die Zeilenschaltung?
Ne, bei der zsh kommt es da leider auch einzeilig raus.

Code: Alles auswählen

all_as_array = ("${(s/%/)all}") # splitt all beim %
Das '(s/%/)' ist eine Art sed-Anweisung? Dann wäre das nur eine Entfernung der %.
Gewollt war vielleicht sowas '(s/%.*/)' (k.A.), also Entfernung des Zeilenrestes,
aber zeilenweise arbeitend?
Nein, das ist ein split bei der zsh:

Code: Alles auswählen

a="a:b:c:d:e"
b=("${(s/:/)a}")
for i in $b;do echo $i;done
a
b
c
d
e
Damit könntest Du das array gesteuerter aufbauen:

Code: Alles auswählen

acpi | tee - |
while read kind nr status charge rest; do
    echo K$kind N$nr S$status C$charge
done
Das sieht wirklich ganz gut aus (auch wenn ich status für die zsh umbenennen musste), aber mein array bleibt leider leer:

Code: Alles auswählen

acpi | while read kind nr stat charge rest; do batteries=("${batteries[@]}" "$charge") && echo K$kind N$nr S$stat C$charge; done
Ich hab erwartet, dass jetzt die beiden charges in $batteries drin stehen. Bei mir ist $batteries aber leer.
Mache ich da irgendetwas offensichtliches falsch?

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: ZSH - splitting von Strings

Beitrag von rendegast » 29.07.2012 13:30:16

Gerade mal zsh installiert.
Eine Zeilenschaltung bei einer Variablenzuweisung bleibt erhalten
(ist aber vielleicht auch eine default-Einstellung der squeeze-zsh)

Deine Variante mal "debuggen"?

Code: Alles auswählen

... ; do batteries=("${batteries[@]}" "$charge") ; done
->
... ; do echo batteries=("${batteries[@]}" "$charge") ; done
Wird die Variante auch unter zsh ausgeführt?


Deine Variante funktioniert hier mit einer Testeingabe:

Code: Alles auswählen

$ cat /tmp/acpi_tee 
Battery 0: Discharging000, 97%, discharging at 000 zero rate - will never fully discharge.
Battery 1: Discharging111, 93%, discharging at 111 zero rate - will never fully discharge.
Battery 2: Discharging222, 91%, discharging at 222 zero rate - will never fully discharge.
Die erfolgte Zuweisung:

Code: Alles auswählen

$ set | grep --binary-files=text batter
batteries=('' 97%, 93%, 91%,)

resp.
$ echo $batteries[@]                  # oder einfach $batteries
97%, 93%, 91%,
Das erste Element ist leer, das kann verhindert werden durch Entfernung von Quotes:

Code: Alles auswählen

... batteries=("${batteries[@]}" "$charge") ...
->
... batteries=(${batteries[@]} "$charge") ...
(Bei bash müßten die Quotes aber bleiben, da sonst die Array-Elemente zerissen würden.
Außerdem existiert unter bash das array nur innerhalb der while-Schleife. Es müßte irgendwie "nach oben" exportiert werden.)

Eine Spielerei mit dem Element:

Code: Alles auswählen

... batteries=(${batteries[@]} "$nr $charge") ...
->
$ set | grep --binary-files=text batter
batteries=('0: 97%,' '1: 93%,' '2: 91%,')
Zuletzt geändert von rendegast am 29.07.2012 14:23:57, insgesamt 2-mal geändert.
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Liffi
Beiträge: 2345
Registriert: 02.10.2004 01:33:05

Re: ZSH - splitting von Strings

Beitrag von Liffi » 29.07.2012 14:14:22

Ah. Mir ist gerade (nach einem Mittagsschlaf) ein kleiner Fehler von mir aufgefallen.
In einem Skript habe ich deine Variante eingebaut und dann die Gesamtausgabe noch mal einer Variablen zugewiesen:

Code: Alles auswählen

a=$(acpi| while read kind nr stat charge rest; do batteries+=("$charge") && echo K$kind N$nr S$stat C$charge; done)
Das ist natürlich Unsinn. $() benutzt eine subshell und $batteries existiert danach nicht mehr.
Außerdem benutze ich hier eine kleine Abkürzung der zsh für das Pushen auf ein Array:

Code: Alles auswählen

batteries+=("$charge")
Jetzt gehts.

Danke vielmals für deine Hilfe!

Antworten