[BASH] Frickler-Pipes

  • Hallo zusammen,

    jeder kennt sie, jeder nutzt sie - nur die wenigsten blicken voll durch. Auch wenn ich überwiegend in der Programmiersprache Icon programmiere, so ganz komme ich an dem Thema Pipes nicht vorbei - und, ehrlich gesagt, nutze ich Pipes wesentlich häufiger, als man es von einem Hochsprachen-Programmierer erwarten würde.


    Was ist eine Pipe?

    Eine Pipe ist eine Verkettung von Linux-Kommandos, deren Ergebnis vom ersten Befehl an den zweiten Befehl usw. weitergeben werden, bis schließlich eine Information ermittelt wird, die - ohne Pipe - nicht so leicht und einfach hätte ermittelt werden können.

    Ich möchte in diesem Thread gern erreichen, dass jeder, der eine Pipe geschrieben hat, diese mit einer kurzen Beschreibung hier hereinstellt. Damit kann der Zweck erfüllt werden, dass jeder, der eine Pipe benötigt, sich hier bedienen kann.

    Ansonsten sucht man sich hier leider auch wieder einen Wolf, findet nichts und kippt eine weitere Frage ein

    Das Ganze stelle ich mir so vor, dass eine Pipe eingestellt wird und ich im Beitrag #1 ein Inhaltsverzeichnis pflege und auf die einzelnen Pipe-Beiträge verweise.

    Beste Grüße

    Andreas


    Inhalt Frickler-Pipes

    1. Ermittlung des freien SD-Kartenspeichers #2, #3, #4, #5
    2. Auflisten aller im System angelegten User #6, #7
    3. Ermitteln der Anzahl der Prozessor-Kerne #8
    4. Anzahl der möglichen Taktgeschwindigkeiten #9, #10
    5. GPS-Empfänger - Geräte-Name, sendet wohin, sendet was #16,#17
    6. Läuft ein Prozess mit bekannter PID noch? #21,#22,#23,#24,#25,#26
    7. Datumszeitstempel der aktuellsten Datei in einem Verzeichnis #29,#30, #31

    8. Ausgabe der 100 größten Dateien #33

    9. Anzahl der Dateien in einem Verzeichnis #37

    10. IP-Adresse der WLAN0-Schnittstelle #38 - auch #40, #41

    11. IP-Adresse der ETH0-Schnittstelle #39, #40, #41

    12. Device-Namen einer gerade eingelegten SD-Karte ermitteln #83

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    16 Mal editiert, zuletzt von Andreas (26. Januar 2021 um 22:14) aus folgendem Grund: Links eingefügt

  • Ermittlung des freien SD-Kartenspeichers

    Das Linux-Kommando [font="Courier New"]df[/font] liefert z.B. folgende Info

    Code
    Dateisystem    1K-Blöcke Benutzt Verfügbar Verw% Eingehängt auf
    /dev/root        7459532 4111100   2995108   58% /
    devtmpfs          242612       0    242612    0% /dev
    tmpfs              49380     272     49108    1% /run
    tmpfs               5120       0      5120    0% /run/lock
    tmpfs              98740       0     98740    0% /run/shm
    /dev/mmcblk0p1     57288   20232     37056   36% /boot
    tmpfs              16384       0     16384    0% /mnt/RAMDisk

    Interessiert bin ich an dem Wert 58.

    Ich brauche also die zweite Zeile des Kommandos [font="Courier New"]df[/font]. Dies macht die Pipe:

    Code
    df | head -n2

    Zwischenergebnis:

    Code
    Dateisystem    1K-Blöcke Benutzt Verfügbar Verw% Eingehängt auf
    /dev/root        7459532 4111116   2995092   58% /


    Hiervon brauche ich jetzt die letzte Zeile und komme zur neuen Pipe:

    Code
    df | head -n2 | tail -n1

    Zwischenergebnis:

    Code
    /dev/root        7459532 4111116   2995092   58% /


    Hiervon benötige ich die Spalte 5 und komme zur neuen Pipe:

    Code
    df | head -n2 | tail -n1 | awk {'print $5'}

    Zwischenergebnis:

    Code
    58%


    Davon schneide ich mit einem scharfen Messer die ersten beiden Zeichen heraus - ich gehe mal davon aus, dass ein System mit voller SD-Karte nicht laufen wird - der Fall 100% wird nicht eintreten.

    Code
    df | head -n2 | tail -n1 | awk {'print $5'} | cut -c 1-2


    Endergebnis:

    Code
    58

    Diese Frickler-Pipe in einer Hochsprache wie Icon umgesetzt, sieht dann so aus:

    Code
    if pipe := open("df | head -n2 | tail -n1 | awk {'print $5'} | cut -c 1-2", "p") then
    {   f := read(pipe)
      close(pipe)
    }

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (23. November 2015 um 13:14)

  • Eigentlich wollte ich ne Pause machen - kann mich aber nicht zurückhalten :fies:

    Dein Satz zum "Was ist eine Pipe?" ist eigentlich schon Aussage genug um einfach zu verstehen das man im Prinzip jeden Konsolen Befehl, bzw eigentlich generell jede Ausgabe, über Pipes kombinieren/verschachteln kann.

    Das Problem an diesen Pipes ist allerdings, das es immer mehrere Möglichkeiten gibt um ans gleiche Ziel zu kommen.
    In deinem #2 Fall zum Beispiel würde ich 'head' und 'tail' weg lassen und stattdessen den Weg über den Devicenamen gehen, da man diesen eigentlich anpeilt. Also normal geht man daher und denkt sich "ich möchte wissen wie viel Speicherplatz meines Laufwerks ist, entweder noch Frei oder wird Verwendet". In dem Fall weiß man dann eigentlich den Gerätenamen als welches es eingebunden wurde, zum Beispiel /dev/sda1 für die erste USB-Festplatte btw USB-Stick.
    Um so mehr Befehle man in den Pipes nutzt, um so langsamer ist das ganze. Das fällt bei so wenigen bzw kurzen Pipes zwar nicht auf - aber lass das mal 10 Pipes sein dann kann man sowas schon merken ;)

    In dem Fall käme dann auch gleich der ziemlich nützliche und oft verwendete Befehl grep zum Einsatz: Man möchte in einer Ausgabe oder Logdatei nach etwas bestimmten suchen und "greift" sich die Zeile mithilfe eines Suchworts. Für den Befehl kann man auch sog. Regular-Expressions (regex) verwenden...

    Angelehnt an Dein Beispiel sähe das also wie folgt aus:

    Code
    df | grep /dev/root

    Somit hätte man schon mal nur die eine Zeile die uns interessiert.

    Dann käme der awk Befehl den ich ebenfalls fast genau so verwenden würde - allerdings habe auch ich mir die falsche Syntax angewöhnt, eigentlich soll man erst ' setzen und danach { ebenso wie erst } und dann '. Es funktioniert zwar auch so wie du es geschrieben hast und ich mir auch angewöhnt habe, aber lieber korrekt erklärn :fies:

    Code
    df | grep /dev/root | awk '{print $5}'

    Nun würde ich allerdings nicht den cut Befehl nutzen sondern stattdessen tr, mit dessen Hilfe man sowohl Zeichen raus löschen aber auch ersetzen kann. Das hat eben den Vorteil das es keine Rolle spielt wie viel Zeichen es sind die mich interessieren, ob 2 oder 3 Stellen ist nicht von Belang. Dein Problem bezüglich 100% fällt hierbei also weg.

    Code
    df | grep /dev/root | awk '{print $5}' | tr -d '%'

    wichtig ist hier unbedingt das Leerzeichen zwischen -d und '%' zu haben, was bei anderen Befehlen nicht immer der Fall sein muss. Aber ob man ' oder " nutzt spielt aber kaum keine Rolle.

    Sofern es sich nicht um "/dev/root/" handelt kann man das Device-File auch direkt dem df Befehl übergeben, würde uns in diesem Fall aber nicht allzuviel bringen da dann auch wieder die Spaltenüberschrift mit ausgegeben wird. Wenn man allerdings Netzwerk-Freigaben eingebunden hat aber man möchte nur die Information von den lokalen Laufwerken, würde das weitaus schneller gehen lieber direkt "df /dev/mmcblk0p1" auszuführen, denn das auslesen der Laufwerksinformationen bremst übers Netzwerk den df Befehl aus.

    awk ist ein sehr sehr mächtiges und schnelles Hilfsmittel. Mit awk könnte man sich auch alle Pipes sparen. Die Syntax ist allerdings auch nicht so einfach.. Aber das überlasse ich hier jemand anderem, wollts nur mal erwähnt haben :fies:

  • Wie man an Tell's Beispiel gut sieht kann man das auch mit nur einer Pipe lösen.
    Erklärend zu der Zeile von Tell:

    /root/ ist, ähnlich wie beim sed Befehl, der Begriff bzw Filter nachdem gesucht werden soll, er hat dort also nicht aus Faulheit /dev weggelassen. Man muss also "/ /" haben und da drin das zu suchende einfügen. Auch hier kann man Regular-Expressions (regex) verwenden.
    Ein einfaches Beispiel um das zu demonstrieren:

    Code
    echo -e "hallo\n welt\n da\n draussen\n wie\ngehts" | awk '/d/'

    Und dann folgt eben das Ersetzen mithilfe von sub() des Zeichens "%" durch "" also nichts und anschließend Ausgabe der 5. Spalte... Zu letzterem könnte man vielleicht noch erwähnen das eine Spalte Standardmäßig anhand von Leerzeichen oder Tabs erkannt wird, man kann das aber auch mithilfe der Option -F verändern.

  • Auflisten aller im System angelegten User

    Code
    cat /etc/passwd | grep "/home" |cut -d: -f1

    In Icon:

    Code
    procedure users()
        list_of_users := []
        if pipe := open("cat /etc/passwd | grep \"/home\" |cut -d: -f1", "p") then
        {   while put(list_of_users, read(pipe))
            close(pipe)
        }
        return list_of_users
    end


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (3. Oktober 2017 um 11:43) aus folgendem Grund: Zeile while put( korrighiert

  • Hallo zusammen,


    gestern habe ich eine hübsche Anwendung geschrieben, die (ressourcenschonend wie immer) dieses mal Taktgeschwindigkeiten der Prozessorkerne graphisch darstellt.

    Da ich mich dabei nicht nur auf Ein-Prozessor-Systeme beschränken wollte, stellte sich als Erstes die Frage:

    Wie ermittelt man die Anzahl der Prozessorkerne in einem Linux-System?

    Als Pipe so:

    Code
    cat /proc/cpuinfo | grep processor | wc -l

    Und verpackt in einem Icon-Programm so:

    Code
    ...
    
    
       if pipe := open("cat /proc/cpuinfo | grep processor | wc -l", "p") then
       {   kerne := read(pipe)
           close(pipe)
       }
    
    
    ...

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (16. Mai 2016 um 18:12)

  • Hallo zusammen,

    und hier noch die Pipe zur Abfage der möglichen Taktgeschwindigkeiten der Prozessorkerne

    Code
    cpufreq-info | grep "mögliche Taktfrequenzen" | head -n 1 | awk '{print $3, $7, $9, $11, $13, $15, $17, $19, $21, $23, $25, $27, $29, $31}'


    Ggf. muss [font="Courier New"]cpufreq-info[/font] installiert werden.

    Und die Umsetzung in Icon:

    Code
    ...
        if pipe := open("cpufreq-info | grep \"mögliche Taktfrequenzen\" | head -n 1 | awk '{print $3, $7, $9, $11, $13, $15, $17, $19, $21, $23, $25, $27, $29, $31}'", "p") then
        {   zeile := read(pipe)
            write(z)
            close(pipe)
        } 
        ...

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (26. Mai 2016 um 20:25)

  • Der Thread ist schon alt - aber ich bin erst eben drüber gestolpert.

    Mir ist nicht ganz klar was der Sinn dieses Threads ist. Die Linux Philospie ist - mal ganz zusammengedampft - einfache Programme zu schreiben und man baut die gewünschten Ergebnisse mit den einfachen Programmen zusammen wobei man die Ergebnisse des einen Programms mit ein oder mehreren Programmen per Linux pipes in einerm Fliessband zusammenbindet und final sein gewünschtes Ergebnis erhält.

    Man benutzt also die vielen kleinen einfachen Linuxbausteine und kombiniert sie anstelle dass man jedes mal ein hochkomplexes Programm für ein konkretes schreibt welches ein gegebenes Problem löst. Letztendlich ist das die Realisierung des divide and conquer Prinzips in der Informatik.

    Ich benutze häufig immer wieder neue diverse Befehlskombinationen (Neudeutsch Pipes). Das ist ja das Schöne an Linux. Wenn ich die hier alle poste komme ich aus dem Posten nicht heraus. Es finden sich jeden Tag neue LinuxBefehlsPipeKombinationen um ein Problem zu lösen.

    Kurzum ... ich habe ein Problem den Sinn dieses Threads zu verstehen :no_sad:

  • Hallo Framp,


    Der Thread ist schon alt - aber ich bin erst eben drüber gestolpert.


    Dieser Thread lebt von immer wieder neuen Ideen...


    Mir ist nicht ganz klar was der Sinn dieses Threads ist.


    Meine ursprüngliche Intention bestand darin, einfach eine kleine Sammlung von Pipes anzustoßen. Hinter der Linux-Philosophie stehe ich auch voll und ganz. Nur dies erfordert, dass sich der Anwender / Nutzer auch damit auseinandersetzt. Und so wie ich das seit rund 8 Jahren Linux einschätze, installieren sich die meisten Linux sowie früher Windows und erwarten, dass die Kiste genauso läuft. Macht sie bzgl. Standardanwendungen auch.

    Es gibt aber nicht umsonst so viele Programme zum Eingeben von Kommandozeilen. Und hier ist Eigeninitiative des Anwenders / Nutzers gefragt.

    Nur wenige beschäftigen sich mit den unzähligen Linux-Programmen und seinen Parametern.
    Nur wenige nutzen [font="Courier New"]man[/font].
    Und nur die wenigsten haben mal was von [font="Courier New"]xman[/font] gehört - geschweige dieses überhaupt mal eingesetzt.
    Mit [font="Courier New"]man[/font] erfährt man sehr vieles bis alles zu einem Linux-Kommando, dessen Namen man kennt. Mit [font="Courier New"]xman[/font] erhält man über dessen Strukturierung überhaupt Kenntnis diverser Linux-Kommandos.

    Viele fragen einfach nur: Wie geht dies? Wie geht das?



    Ich benutze häufig immer wieder neue diverse Befehlskombinationen (Neudeutsch Pipes). Das ist ja das Schöne an Linux. Wenn ich die hier alle poste komme ich aus dem Posten nicht heraus. Es finden sich jeden Tag neue LinuxBefehlsPipeKombinationen um ein Problem zu lösen.


    Eben darum! Du, einige wenige andere und ich, wir kennen uns mit den Linux-Kommandos einigermaßen bis gut aus und sind in der Lage, Pipes mit annähernd beliebigem Verhalten zu entwerfen. Wenn ich für eine Pipe wenige Minuten benötige, bis sie so funktioniert, wie ich mir das vorstelle, dann suche ich im Internet überhaupt nicht nach Alternativen - sondern setze meine Lösung ein.


    Kurzum ... ich habe ein Problem den Sinn dieses Threads zu verstehen :no_sad:


    ... Und für all die anderen ist dann dieser Thread... Die können sich bedienen, berieseln lassen, konsumieren.
    ... Und so meine Hoffnung: Es reicht irgendwann ein Verweis auf diesen Thread anstatt immer wieder Wissen so zu verteilen, dass man nichts mehr wiederfindet.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.


  • awk ist ein sehr sehr mächtiges und schnelles Hilfsmittel. Mit awk könnte man sich auch alle Pipes sparen. Die Syntax ist allerdings auch nicht so einfach.. Aber das überlasse ich hier jemand anderem, wollts nur mal erwähnt haben :fies:

    Jupp, nur leider wird awk von den meisten nur dazu benutzt einfach das n-te Element einer Zeile zu extrahieren.

    Code
    df | awk '/\/dev\/root/ { print $5 }' | tr -d '%'

    benutzt gleich noch die von Dir schon angesprochene regex Suchfunktion die es auch per grep gibt.

    Eine andere Möglichkeit Elemente aus einer Zeile ohne awk zu extrahieren ist eine while read loop in die man die Ausgabe eines Befehls reinsteckt. Z.b.

    Code
    while read fs bl usd ava use mnt; do echo $fs $use; done < <(df) | grep root | tr -d '%' | cut -d' ' -f2


    Man könnte auch noch die Abfrage auf root in die while Schleife reinstecken aber es geht ja darum kleine Tools intelligent zu kombinieren und nicht zu programmieren :D

  • Hallo Framp,


    Man könnte auch noch die Abfrage auf root in die while Schleife reinstecken aber es geht ja darum kleine Tools zu kombinieren und nicht zu programmieren :D

    :thumbs1: - aber ich denke mal, jedes Mittel das zum Ziel führt, heiligt die Mittel.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • ...Wenn schon Frickler-Pipes, dann richtig!...


    Richtig oder falsche Frickler-Pipes gibt es nicht :no_sad: . Wichtig ist - wie schon unser Bundeskanlzer Kohl sagte - was hinten rauskommt :D
    Ziel ist es doch immer ein Problem schnell ohne grosses Programmieren durch intelligente Kombination von den vielen kleinen zur Verfügung stehenden Linux Tools zu lösen.

    Und dazu passt wie Andreas eben schrieb:

    Zitat von Andreas

    ... jedes Mittel das zum Ziel führt, heiligt die Mittel...

    .

  • Hallo zusammen,

    wenn man wissen will, als welches Gerät ein per USB an den Raspberry Pi angeschlossener GPS-Empfänger im System bekannt ist:

    Code
    ls -l /dev/* | grep gps | awk {'print $9'}


    Antwort:

    Code
    /dev/gps0

    Wenn man wissen will, an welche serielle Schnittstelle dieser GPS-Empfänger seine Daten sendet:

    Code
    ls -l /dev/* | grep gps | awk {'print $11'}


    Antwort:

    Code
    ttyACM0

    Hier darf sich der unbedarfte Anwender noch ein [font="Courier New"]/dev/ttyACM0[/font] dazu denken...

    ... oder nutzt dafür auch eine Pipe:

    Code
    echo "/dev/$(ls -l /dev/* | grep gps | awk {'print $11'})"

    Wenn man wissen möchte, was der GPS-Empfänger so an die serielle Schnittstelle sendet, kann man das mit

    Code
    cat /dev/ttyACM0

    oder

    Code
    cat /dev/gps0


    erfahren.

    Dafür gibt es natürlich eine Frickler-Pipe - wenn schon, denn schon:

    Code
    cat "/dev/$(ls -l /dev/* | grep gps | awk {'print $11'})"


    oder auch

    Code
    cat $(ls -l /dev/* | grep gps | awk {'print $9'})


    Die Programmierung in Icon folgt ...

    Code-Deutung:
    In der Hauptprozedur [font="Courier New"]main()[/font] beginnt das Programm wie immer. In der ersten Schleife

    Code
    while *piper("ls -l /dev/* | grep gps") = 0 do
    {   if /warning then write("Bitte GPS-Empfänger anschließen!")
       warning := 1
       delay(1000)
    }


    wird geprüft, ob überhaupt ein GPS-Gerät angeschlossen ist. Wenn nicht (erkennbar daran, dass die Pipe kein Ergebnis liefert), dann wird eine Meldung abgesetzt und auf diesen misslichen Zustand hingewiesen. Aber nur einmal. Diese einmalige Meldung erreiche ich durch Abfrage der Variablen [font="Courier New"]warning[/font]. Bei der ersten Abfrage ist diese Variable noch nicht gesetzt - und trägt den Wert [font="Courier New"]&null[/font]. Die elegantere Abfrage ist [font="Courier New"]/warning[/font], was bedeutet: Ist [font="Courier New"]warning[/font] nicht definiert, dann schreibe etwas...

    Anmerkung: [font="Courier New"]/warning[/font] ist nicht zu verwechseln mit [font="Courier New"]\warning[/font]... Letzteres bedeutet: Ist die Variable (mit etwas ungleich [font="Courier New"]&null[/font]) belegt... Diese Notation hat auch einige Zeit gebraucht, bis sie sich in meinem Kopf festgesetzt hat. Wem das ähnlich gehen sollte, hier eine kleine Eselsbrücke. Ich will prüfen, ob eine Variable [font="Courier New"]&null[/font] ist oder nicht, gleichbedeutend mit noch nie benutzt oder durch eine Zuweisung auf diesen Wert gebracht. Wenn man [font="Courier New"]&null[/font] liest, denkt man leicht an die Zahl 0. Diese Zahl hat eine Form, die wie ein Reifen oder Rad aussieht ... und gut rollen kann. Aufwärts leichter als jede andere Form. Wer hoch fliegt, fällt tief... Also plumpst einem die 0 ... ensprechend [font="Courier New"]&null[/font] ... auf die Füße. Damit hat man sich gemerkt, dass [font="Courier New"]/warning[/font] auf Identität mit [font="Courier New"]&null[/font] prüft.
    Sobald man sich dies bildhaft vorstellen kann, braucht man sich [font="Courier New"]\warning[/font] nicht mehr zu merken... Ist genau das Gegenteil.


    Nach Absetzen der Meldung wird die Variable auf einen Wert ungleich [font="Courier New"]&null[/font] gesetzt und eine Sekunde gewartet.
    Beim nächsten Durchlauf ist [font="Courier New"]warning[/font] bekannt, die Abfrage [font="Courier New"]/warning[/font] ist nicht mehr erfüllt - eine weitere Meldung bleibt aus.
    Diese Schleife wird solange durchgeführt, bis der Strom ausfällt, der Anwender das Programm beendet, oder sich doch noch mal erbarmt, irgendeinen GPS-Empfänger in sinnvoller Weise an USB, UART oder etwas anderes geeignetes anzuschließen. Dann nämlich ist die Bedingung erfüllt, weil die Auswertung der Pipe eine Rückmeldung liefert, die aus mehr als 0 Zeichen besteht.

    Im darauffolgenden Teil

    Code
    gps_dev := piper("ls -l /dev/* | grep gps | awk {'print $9'}")
    gps_interface := piper("ls -l /dev/* | grep gps | awk {'print $11'}")
    write("GPS-Empfänger gefunden und als ", gps_dev, " identifiziert")
    write("GPS-Empfänger ", gps_dev, " sendet an die Schnittstelle ", gps_interface)
    write("die als ", piper("echo \"/dev/\"$(ls -l /dev/* | grep gps | awk {'print $11'})"), " in eigenen Anwendungen anzusprechen ist")


    wird der Name des GPS-Geräts ausgelesen und das Interface ermittelt, in das das GPS-Gerät schreibt. Die Daten werden angezeigt.
    Eine Anmerkung zu dem [font="Courier New"]\"[/font]. Wenn man sich die Pipes anschaut, die in der Konsole eingegeben wurden, dann enthalten diese gelegentlich mal ein Anführungszeichen [font="Courier New"]"[/font]. In Icon ist dies die Einleitung einer Zeichenkette - und auch deren Ende. Dies bedeutet, dass ein Anführungszeichen innerhalb einer Zeichenkette anders codiert werden muss, da es sonst anders als beabsichtigt gedeutet wird. Die geschieht mit dem Schrägstrich [font="Courier New"]\[/font].
    Schön ist, dass die gleichen Ergebnisse geliefert werden wie einst auf der Konsole - der Icon-Code funktioniert also.

    Und im letzten Drittel

    Code
    write("Der GPS-Empfänger sendet:")
    repeat
    {   p := piper("head \"/dev/$(ls -l /dev/* | grep gps | awk {'print $11'})\" -n 10", "END=$GPGLL")
       case type(p) of
       {"string": write(p)
        "list": every write(!p)
       }
    }


    wird dann dass, was die definierte Schnittstelle empfängt, angezeigt.

    Bleibt noch die Funktion [font="Courier New"]piper()[/font] übrig.


    Hierbei handelt es sich um eine Experimental-Funkion aus meiner Icon-Werkzeugkiste (Icon-Tool-Kit, ITK), die momentan bei jeder Anwendung angepasst und verfeinert wird.

    Demnach liefert eine Pipe momentan

    • entweder kein Ergebnis = leere Zeichenkette oder leere Liste
    • ein Ergebnis bestehend aus einer Zeile Text oder einer Liste aus einem einzigen Eintrag
    • ein Ergebnis bestehend aus mehreren Textzeilen, die in einer Liste mit mehreren Einträgen ernthalten sind

    Diese Version von [font="Courier New"]piper()[/font] übergibt die übergebene Zeichenkette und übergibt sie dem [font="Courier New"]open()[/font]-Befehl, der hier in der Form einer Eingabe-Ausgabe-Weiterleitung (Pipe) ausgeführt wird. Deswegen auch [font="Courier New"]"p"[/font] als zweites Argument. Das [font="Courier New"]p[/font] steht sinnvollerweise für ... na ... :s ... ach ... Pipe. Kann man sich wenigstens gut merken.

    Anmerkung: Das meiste, was ich bisher (Icon-Tutorials, etliche Beiträge zu irgendwelchen Lösungen mittels Code) bzgl. der Programmiersprache Icon geschrieben habe, gilt für Umsetzungen auf

    • dem Raspberry Pi mit dem Betriebssystem Raspbian (Wheezy, Jessie),
    • PC mit Betriebssystem Ubuntu und sicherlich so ziemlich allen Linux-Distributionen und
    • PC mit dem Betriebssystem Windows (Win 95, Win 98, XP).


    Blöderweise werden Pipes in dieser Form unter Windows nicht unterstützt.

    Der zweite Parameter [font="Courier New"]endcriteria[/font] dient dazu, dass [font="Courier New"]piper()[/font] erkennen kann, wann genug Daten gesammelt sind. Ist dieser Parameter nicht definiert (s. die ersten Aufrufe in der Hauptprozedur [font="Courier New"]main()[/font]), dann wird gesammelt, als wenn es keinen Morgen gäbe:

    Code
    if /endcriteria then while put(p, read(pipe))


    diese Zeile bedeutet sinngemäß, wenn kein Endekriterium definiert ist, dann lese alle Einträge der Pipe, die geliefert werden können. Die meisten Pipes sind endlich - also passt das hier (ersteinmal).
    Praktischerweise enthalten die zuvor definierten Pipes entweder kein oder nur ein einziges Ergebnis, weshalb kein Endekriterium erforderlich war.

    Die Pipe, die die GPS-Daten sammelt, hat dann jedoch ein Problem. Ohne ein Endekriterium würde sie sammeln und sammeln und sammeln. Bis der Speicher voll ist. Das ist unpraktisch. Deswegen habe ich ein Endekriterium

    Code
    "END=$GPGLL"


    definiert, was bedeutet, dass die Datensammlung beendet werden soll, sobald die Zeichenkette [font="Courier New"]$GPGLL[/font] in einem Datensatz enthalten ist. Das macht bei meinem GPS-Empfänger Sinn, weil dies die letzte Zeile darstellt, die zur geltenden Sekunde geliefert wird. Wer einen GPS-Empfänger mit anderen Datensätzen haben sollte, ersetzt einfach diesen Eintrag.

    Das [font="Courier New"]case[/font]-Konstrukt stellt eine Fallunterscheidung dar... und bietet Platz für viele Erweiterungen. Z.B. kann es Fälle geben, in denen man nur eine bestimmte Anzahl von Zeilen haben möchte, oder nur eine bestimmte Zeile. Oder man will einen Timeout definieren. Oder ... oder ... oder... .

    Versucht man ein Endekriterium anzuwenden, das im case-Konstrukt nicht definiert wurde, dann wird auch eine Meldung abgesetzt, die auf diesen misslichen Umstand hinweist.

    Ausgabe (ohne GPS-Daten ;) :(


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (18. September 2016 um 12:43)

  • Hallo Tell,


    Ich weiss, in diesem Thread sind keine Verbesserungsvorschlaege erwuenscht...


    Wie kommst Du denn darauf? Ich bin für jede Verbesserung sehr dankbar. Meine Stärken liegen auf anderen Gebieten als BASH und Pipes... ich nutze sie nur. Und freue mich, wenn da was funktioniert. Der Lerneffekt ist zwar enorm - aber die Vergesslichkeit auch, weil ich's eben nicht regelmäßig aktiv nutze.



    Diese Pipe reizt mich aber trotzdem zu einem Kommentar:

    Code
    ls -l /dev/* | grep gps | awk {'print $9'}

    Ich haette das einfach so gemacht:

    Code
    ls -1 /dev/*gps*

    Minus EINS, nicht ELL

    ls -1 kenne ich z.B. gar nicht... :danke_ATDE:

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (15. September 2016 um 21:50)

  • Hallo zusammen,

    Code in der Programmiersprache Icon zur Anwendung der GPS-Pipes habe ich in Beitrag #16 aufgenommen. Die anderen hier besprochenen GPS-Pipes funktionieren ebenso wie die, die ich dann in Icon übernommen habe. Das hat nichts mit Geschmack oder Funktionalität zu tun...

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (18. September 2016 um 10:13)

  • ...Wie kommst Du denn darauf? Ich bin für jede Verbesserung sehr dankbar...

    Sehe ich auch so. Es gibt so viele Optionen bei den Linux Tools und i.d.R. kennt man nur einen Subset. Deshalb sind solche Hinweise auf weitere Tooloptionen und Lösungswege sehr hilf- und lehrreich.
    Ausserdem gibt es wie immer viele Wege nach Rom. Je nach Erfahrung ist der bei Linux länger oder kürzer und ein jeder ist doch dankbar wenn er lernt wie er nach Rom kommt ohne über die Arktis reisen zu müssen :lol:

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!