ubuntuusers.de

Stream-Info auswerten ~> Notifier

Status: Ungelöst | Ubuntu-Version: Ubuntu 10.04 (Lucid Lynx)
Antworten |

Ryuno-Ki

Avatar von Ryuno-Ki

Anmeldungsdatum:
7. März 2011

Beiträge: 1105

Wohnort: Stuttgart

Guten Abend,

so, bin jetzt nach drei Stunden schon etwas gefrustet - awk, sed udgl. sind mir ein wenig zu kryptisch >_<

Denke aber, dass sie am günstigsten werden ...

Folgendes. Ich lade mir die Stream-Daten eines Webradiosenders (mit Einverständnis der Betreiber) via wget als Text-Datei herunter.

Aufbau ist in etwa folgender:

{ "timeout_seconds": 1800, "timeout": false, "mod": Moderator, "mod2": Alternativmoderator, "show": "Showthema", "song": "Interpret - Songtitel", "listeners": 2, "bitrate": 192 }

mod und mod2 können Leerzeichen und Apostrophen u.Ä. enthalten. Genauso wie in Showthema und Interpret/Songtitel.

Mich interessiert hier eigentlich nur die Angaben Alternativmoderator, Titelbezeichnung, Interpret und Songtitel, damit ich sie via

notify-send -i /usr/share/rhythmbox/icons/hicolor/32x32/status/rhythmbox-notplaying.png "$interpret--$titel" "$dj--$showthema"

an den Notifier schicken kann.

Mein Versuch:

grep "song" /home/andre/exodus-stream-status.txt | cut -d',' -f5 | cut -d':' -f2
grep "song" /home/andre/exodus-stream-status.txt | cut -d',' -f6 | cut -d':' -f2

bereitet den Datensatz erst einmal entsprechend auf (Interpret + Songtitel), allerdings noch mit Anführungszeichen.

Außerdem bekomm ich das Resultat nicht mit $(...) in eine Variable ... gibt es hier geschicktere Befehle?

cut hab ich zumindest verstanden ☺

Wär cool, wenn mir jemand heute Abend / die Woche Nachhilfe geben könnte.

Ryu

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Hi Ryu,

natürlich kannst Du die Auswertung so einer Datei auch mit der Bash machen, am besten zeilenweise.
Ich gehe jetzt mal davon aus, dass in den Moderatornamen, Titeln usw. kein Komma weiter vorkommt. Dann kann man die Zeile nämlich anhand der Kommas in Felder zerteilen:

while read zeile ; do                               # Schleife: zeilenweise lesen
        IFS=","                                     # Trennzeichen Komma einstellen
        feld="$(zeile)"                             # Array-Zerlegung in Felder

        echo "${feld[3]}"                           # das komplette "mod2"-Feld ausgeben
        echo "${feld[3]#*\": }"                     # nur den Inhalt von "mod2" ausgeben (alles bis zum ": weglassen)
        echo "${feld[5]#*\": }"                     # nur den Inhalt von "song" ausgeben (alles bis zum ": weglassen)
        ## ... usw.
done  <  "/home/andre/exodus-stream-status.txt"     # aus dieser Datei einlesen

Ausführlichere Erläuterungen findest Du in Greg's Bash Guide "Arrays" und Greg's Wiki FAQ073.

LG,

track

Ryuno-Ki

(Themenstarter)
Avatar von Ryuno-Ki

Anmeldungsdatum:
7. März 2011

Beiträge: 1105

Wohnort: Stuttgart

track schrieb:

Hi Ryu,

natürlich kannst Du die Auswertung so einer Datei auch mit der Bash machen, am besten zeilenweise.
Ich gehe jetzt mal davon aus, dass in den Moderatornamen, Titeln usw. kein Komma weiter vorkommt. Dann kann man die Zeile nämlich anhand der Kommas in Felder zerteilen:

while read zeile ; do                               # Schleife: zeilenweise lesen

Macht das "Sinn" bei nur einer Zeile? oO

Ausführlichere Erläuterungen findest Du in Greg's Bash Guide "Arrays" und Greg's Wiki FAQ073.

Schau ich mir heute Nachmittag/Abend vielleicht an ^^ Danke. Muss aber gleich in den Gottesdienst 😉

LG,

track

Gruß zurück!

Ryu

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Servus,

für JSON (so heißt das Datenformat, mit dem du es da zu tun hast – zumindest ist stark davon auszugehen) gibt es genügend „richtige“ Parser. Für Ruby zum Beispiel:

1
2
3
4
5
6
7
8
#!/usr/bin/env ruby

require 'json'

tree = JSON.parse(STDIN.read())

puts tree['mod2']
puts tree['song']

Es liest also von STDIN, parst die Daten und gibt dann zwei Felder gezielt aus.

Beispieldaten (das „Moderator“ und „Alternativmoderator“ müsste noch in Anführungszeichen stehen – ich gehe blind davon aus, dass das im Original so war ☺ ) und Beispielaufruf:

$ cat data
{
        "timeout_seconds": 1800,
        "timeout": false,
        "mod": "Moderator",
        "mod2": "Alternativmoderator",
        "show": "Showthema",
        "song": "Interpret - Songtitel",
        "listeners": 2,
        "bitrate": 192
}
$ ./foo.rb < data
Alternativmoderator
Interpret - Songtitel

Mit awk und Co. brichst du dir an dieser Stelle einen ab. Garantiert.

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Ryuno-Ki schrieb:

Macht das "Sinn" bei nur einer Zeile? oO

Mir war nicht klar, dass da nur eine Zeile ist. Vielmehr war ich von einer Art Playlist ausgegangen, mit mehreren Zeilen in dem von Dir gezeigten Format.

Wenn dem nicht so ist, dann müsstest Du mir nochmal verraten, wie die Daten nun tatsächlich vorliegen.
So wie es Vain beschreibt ? - dann wären seine Hinweise wohl das Gegebene. Sonst müssten wir in den verlinkten Werkzeugkisten nochmal gucken.

track

Ryuno-Ki

(Themenstarter)
Avatar von Ryuno-Ki

Anmeldungsdatum:
7. März 2011

Beiträge: 1105

Wohnort: Stuttgart

Vain schrieb:

Servus,

für JSON (so heißt das Datenformat, mit dem du es da zu tun hast – zumindest ist stark davon auszugehen) gibt es genügend „richtige“ Parser.

Ja, ist JSON.

Es liest also von STDIN, parst die Daten und gibt dann zwei Felder gezielt aus.

Hab ich auch so interpretieren können, danke ☺

Beispieldaten (das „Moderator“ und „Alternativmoderator“ müsste noch in Anführungszeichen stehen – ich gehe blind davon aus, dass das im Original so war ☺ )

War es auch ^^ Allerdings alles in einer Zeile.

$ ./foo.rb < data
Alternativmoderator
Interpret - Songtitel

Hab's erst als .sh gehabt, dann festgestellt, dass ich es als .rb speichern muss.

Trotzdem gibt's ne Fehlermeldung:

1
2
3
4
5

andre@andre-rechner:~$ ./exodus-notifier.rb < exodus-stream-status.txt 
./exodus-notifier.rb:5:in `require': no such file to load -- JSON (LoadError)
	from ./exodus-notifier.rb:5
andre@andre-rechner:~$ 

Quellcode:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/env ruby
# Script, welches den aktuellen Song-Titel von Radio Exodus holt
# und an den Notifier sendet

require 'JSON'

tree = JSON.parse(STDIN.read())

puts tree['mod2']
puts tree['song']

In der Annahme, dass # Kommentar einleitet ... (hab ich aus der Shebang abgeleitet).

Mit awk und Co. brichst du dir an dieser Stelle einen ab. Garantiert.

Dann brauch ich mich in der Richtung im Moment ja nicht weiter beschäftigen 😀 Bin diese Woche gut ausgebucht ... Eigene Gedanken kommen also frühestens nächsten Montag ... wenn du mir vorher nicht helfen magst ☺

Kann ruby eigentlich die Datei direkt herunterladen? Oder muss ich mir ein zweites Script basteln, welches wget als Downloader verwendet und dann das ruby anwirft? Am liebsten wäre es mir, alles in eine Datei zu packen → Funktionale Programmiersprache? Kenn das so von Matlab 😀

Positiv ist jedenfalls die Platformunabhängigkeit von Ruby ... wenn ich da noch eine Lösung für den Download (am besten mit Ruby) finde, kann ich das sogar für Win und Mac deklarieren ...

Muss ich für Ruby noch irgendetwas beachten? Oder läuft das mit der Vorkonfiguration der Installation? Hab nicht die Zeit gefunden, den Wiki-Artikel zu durchzulesen ...

@track: Ja, auch wenn es wegen der 80-Zeichen-Regel im Editor umgebrochen wird, de facto ist es nur eine Zeile ...

Ryu

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Ryuno-Ki schrieb:

Trotzdem gibt's ne Fehlermeldung:

1
2
3
4
5

andre@andre-rechner:~$ ./exodus-notifier.rb < exodus-stream-status.txt 
./exodus-notifier.rb:5:in `require': no such file to load -- JSON (LoadError)
	from ./exodus-notifier.rb:5
andre@andre-rechner:~$ 

Vielleicht musst du das Paket libjson-ruby nachinstallieren. Andererseits muss das „JSON“ im require-Statement auch kleingeschrieben werden.

Dabei sehe ich, dass dein Ubuntu Ruby 1.8 zu haben scheint, während bei mir 1.9.1 läuft. Das ist nicht immer ganz unproblematisch (ähnlich wie bei Python 2 nach Python 3) und müssen wir im Hinterkopf behalten.

Kann ruby eigentlich die Datei direkt herunterladen? Oder muss ich mir ein zweites Script basteln, welches wget als Downloader verwendet und dann das ruby anwirft? Am liebsten wäre es mir, alles in eine Datei zu packen → Funktionale Programmiersprache? Kenn das so von Matlab 😀

Ich mach’ nun auch nicht täglich was mit Ruby, aber die Suchmaschine deiner Wahl wirft zum Beispiel das hier aus:

http://ruby-doc.org/stdlib/libdoc/net/http/rdoc/classes/Net/HTTP.html

Ohne Abfangen von Fehlern:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/env ruby

require 'json'
require 'net/http'

url = URI.parse('http://www.example.com/foo.json')
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) { |http|
	http.request(req)
}

tree = JSON.parse(res.body)
puts tree['mod2']

Muss ich für Ruby noch irgendetwas beachten? Oder läuft das mit der Vorkonfiguration der Installation? Hab nicht die Zeit gefunden, den Wiki-Artikel zu durchzulesen ...

Abgesehen von der Geschichte 1.8 vs. 1.9 sollte es da eigentlich nicht viel zu beachten geben.

Es muss aber auch nicht Ruby sein. Das ist nur das erste, was mir eingefallen war. Für Python gibt es auch einen JSON-Parser (und da finde ich das Holen der Daten via urllib deutlich lesbarer), für Perl sicher auch und sogar für PHP. Aber um genau zu sein: Scroll mal hier ein Stück nach unten. 😉

Python2 ohne Fehlerabfragen und Software-Engineering:

1
2
3
4
5
6
7
8
#!/usr/bin/env python2

import json
import urllib

data = urllib.urlopen('http://www.example.com/foo.json').read()
tree = json.loads(data)
print tree['mod2']

Ryuno-Ki

(Themenstarter)
Avatar von Ryuno-Ki

Anmeldungsdatum:
7. März 2011

Beiträge: 1105

Wohnort: Stuttgart

*hüstel* *Staub wegwisch*

Sooo ...

Hab Semesterferien und vor, mich näher mit der Bash zu beschäftigen. Immer noch das gleiche Problemchen ...

Ich bin bestrebt, dass Ganze ohne Ruby oder Python zu lösen. Bisher schaut's so aus, wenn ich mit wget das noch manuell herunterlade und dann im Terminal bearbeiten möchte:

$ wget -i http://sidebar.radio-exodus.de/stream-status --output-document=exodus-stream-status.info -b > /dev/null
$ tail exodus-stream-status.info | cut -d , -f 6 | cut -d : -f 2 | cut -d - -f 1
 "Asp 
$ tail exodus-stream-status.info | cut -d , -f 6 | cut -d : -f 2 | cut -d - -f 2
 Die Kleine Ballade Vom Schwarzen Schmetterling"

Soweit bin ich ja auch erst einmal ganz zufrieden.

Von C her würde ich jetzt erwarten, dass ich den String zeichenweise einlesen kann, um das " zu entfernen - awk/sed/cut bieten aber offenbar nur zeilenweises Arbeiten an (bzw. cut kommt mit diesem Trennzeichen nicht klar).

Kann man die Ausgabe irgendwie in eine Variable umleiten?

Dann wäre ich sogut wie fertig ☺

Ryu

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Was Du suchst, ist eigentlich eine Art CSV-Parser ... (aber das sind sed und awk von Haus aus nicht)

Hier ist die Sache noch etwas trickreicher, weil immer Pärchen vorliegen, die mit ,   von einander getrennt sind.
Das Gute dabei ist aber, dass man bei awk auch Zeichengruppen als Trenner einstellen kann.

Du kannst damit mit recht überschaubarem Aufwand die letzte Zeile abtrennen und nach Pärchen zerlegen:

track@lucid:~$ awk -F ", " 'END { sub("^[ {]*","",$0); sub("[ }]*$","",$0); for (i=1; i<=NF; i++) print $i }'  exodus-stream-status.info 
"timeout_seconds": 1800
"timeout": false
"mod": null
"mod2": null
"show": "Playlist [Hardmetal]"
"song": "At The Gates - The Burning Darkness"
"listeners": 9
"bitrate": 192 

Damit hättest Du doch schon mal einen Ausgangspunkt.
Jetzt könntest Du natürlich innerhalb des awk- Skripts auch noch eine genauere Bearbeitung vornehmen ...

Und die Umleitung in ein Variablen-Array ginge dann mit der Kombination von Array-Zuweisung und Command Substitution: var=( $( <befehl> ) )

track

Lysander

Avatar von Lysander

Anmeldungsdatum:
30. Juli 2008

Beiträge: 2669

Wohnort: Hamburg

Ryuno-Ki schrieb:

Ich bin bestrebt, dass Ganze ohne Ruby oder Python zu lösen.

Mal abgesehen davon, dass Python in so ziemlich jeder Standardinstallation zu finden sein sollte, wieso suchst Du dann nicht nach Alternativen? Ich habe mittels google und Suche nach JSON und CLI sofort zig Sachen gefunden, u.a. auch durch StackOverflow-Threads. Da war sogar ein reiner Bash-JSON-Parser dabei...

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Oh, JSON heißt das Format, und ist von der Sache ähnlich wie XML aufgebaut ...?

- Das kannte ich noch nicht !

Aber, dann sollte man das wirklich mit einem Parser zerlegen !
(wie bei XML auch. Ganz unten hier bei Stackoverflow die Version mit Python sieht mir auffallend elegant aus)

track

Ryuno-Ki

(Themenstarter)
Avatar von Ryuno-Ki

Anmeldungsdatum:
7. März 2011

Beiträge: 1105

Wohnort: Stuttgart

track schrieb:

Was Du suchst, ist eigentlich eine Art CSV-Parser ... (aber das sind sed und awk von Haus aus nicht)

Was ich suche, ist Erfahrung im Umgang mit der Bash. Also

  1. Bash offline zur Textverarbeitung

  2. Bash mit Online JSON-Parser

  3. JSON-Parser in der Sprache von Rhythmbox → Plugin

So in etwa.

Ich such mir halt Aufgaben, die "schaffbar" erscheinen für einen Anfänger 😉

Bis Ende des Monats hab ich aber auf Prüfungen zu pauken.

Antworten |