bräuchte etwas bash Nachhilfe

  • Hallo,


    bislang habe ich mich meist erfolgreich ums bash-scripten gedrückt, aber jetzt hat es mich doch eingeholt und leider fehlt mir mein perl, bzw. ich weiß nimmer weiter.
    Es geht darum, die Ausgabe eines Befehls einer Variablen zuzuweisen. Das klappt mit var=$(irgendwas) ganz gut.


    Allerdings habe ich jetzt einen Fall, bei dem ein Befehl eine Zeile mit mehreren Worten liefert und einmal möchte ich nur das letzte Wort der Zeile in der Variablen haben, das andere Mal das vierte Wort.


    Muss ich da ne Schleife nehmen und über alle Worte steppen, oder gibt es eine elegantere Möglichkeit (insbesondere für das letzte Wort eine Variante ala perl?).


    Bin für jeden Tip dankbar.


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Das letzte Wort bekommst du z.B. so:


    Code
    echo 'eins zwei drei vier fünf' | tr ' ' '\n' | tail -n1


    oder so:


    Code
    echo 'eins zwei drei vier fünf' | sed -re 's|^.* (.*)$|\1|'


    und es gibt bestimmt noch zig andere Möglichkeiten.

    Arch Linux VDR Packages Projekt
    Pakete: dvd, cdda, epgsearch, femon, filebrowser, live, menuorg, mp3, mplayer, osdpip, devstatus, remote, streamdev, systeminfo, text2skin, vdradmin-am, vompserver, xineliboutput, ...
    Hardware: MSI K8MM3-V, Mobile Sempron 3000+, 512MB RAM, 500GB Samsung HD501LJ, Seasonic S12 330, AVBoard 1.4, Antec NSK2480
    Software: Arch Linux, VDR 1.6.0 + Extensions Patch

  • Hallo,


    Ihr seid ja fix :)


    An die cut-Variante habe ich auch gedacht, nur leider zählt der jedes Lehrzeichen einzeln.


    Die sed-Variante gefällt mir dagegen sehr gut.
    So ähnlich hätte ich es auch in perl gemacht.


    Ich habe mir mal mit so einer Funktion geholfen


    ergibt wie sich jeder denken kann

    Code
    result of test1: [bin]
    result of test2: [Nasenbär]
    result of test3: [hallo]

    aber die sed-Variante ist da doch deutlich eleganter. Und wenn ich nicht weiß, wieviel Worte die Zeile hat, funktioniert es trotzdem.


    Vielen Dank!


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Hi,


    wegen unterschiedlicher Leerzeilen usw. mach ichs immer mit awk:


    Code
    echo "blubb bla fasel" | awk '{print $NF}'


    da sind mir dann leerzeilen, tabs usw. egal.


    cu,


    Quacks

    "Backups are for whimps. Real men upload their stuff on the Internet
    and let the world mirror it".


    --Linus Torvalds

  • Warum mit Kanonen auf Spatzen schiessen... das geht doch auch mit bash-builtins.


    Bash
    #!/bin/bash
    text="   hallo   ich  bin der    Nasenbär"
    IFS=" "
    set -- $text
    echo "zweites Wort:" ${2}
    echo "letztes Wort:" ${!#}
    unset IFS


    Im Prinzip sollte es auch ohne die beiden IFS-Zeilen gehen. So wie's oben steht, trennt er wirklich nur an Leerzeichen.


    Christian

  • Getreu der Devise "kürzer geht immer", hier das gleiche mit Bash-Arrays:


    Code
    IFS=" " output=(`ps --no-headers $$`)
    
    
    echo ${output[*]}
    echo 4th=${output[4]}
    echo last=${output[${#output[*]}-1]}


    Das ps --no-headers $$ ist nur ein Beispielkommando, um etwas interessantes zum Ausgeben zu haben.


    Etwas robuster gegen Syntaxprobleme, falls bestimmte Sonderzeichen in der Ausgabe vorkommen, ist die Verwendung von read:

    Code
    IFS=" " read -a output -r < <(ps --no-headers $$)
    
    
    echo ${output[*]}
    echo 4=${output[4]}
    echo last=${output[${#output[*]}-1]}


    Mit read lassen sich auch mehrzeilige Ausgaben besser verarbeiten:

    Code
    while IFS=" " read -a output -r ; do
      echo ${output[*]}
      echo 4=${output[4]}
      echo last=${output[${#output[*]}-1]}
    done < <(ps --no-headers)



    Gruß,


    Udo

  • Danke für den Tip mit read.


    Beim Kwerlesen bin ich noch über einen netten Nebeneffekt von read gestolpert, der mein get_word ebenso wie einen (zu) oft verwendeten awk überflüssig macht:


    Bash
    #!/bin/sh
    raw="  ein kleiner         test für      irgendwas"
    
    
    echo $raw | while read eins zwei rest; do
       echo "gelesen 1: [$eins]"
       echo "gelesen 2: [$zwei]"
       echo "gelesen R: [$rest]"
    done


    Gruß Geronimo

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

  • Achtung: Bei deiner Schreibweise gelangst du in die Subshell-Falle: Die While-Schleife läuft durch die |-Pipe in einer Subshell, Shell-Variablen gehen am Ende der Schleife verloren.


    Die Schreibweise oben ist davon nicht betroffen, d.H.:

    Code
    while read eins zwei rest; do
      [...]
    done < <(echo $raw)


    Siehe "Process Substitution" im Bash-Manual.


    Gruß,


    Udo

  • Zitat

    Bei deiner Schreibweise gelangst du in die Subshell-Falle


    Huch, Deine Schreibweise hatte ich nicht wirklich registriert/kapiert.


    Sind das wirklich 2x Kleiner-Zeichen nach dem Donut?
    Nennt man das dann eine holländische Pfeife ;)


    Dank Dir jedenfalls für den Nasenstubser. Werde weiter experimentieren.

    Ich bin verantwortlich für das, was ich schreibe, nicht für das, was Du verstehst!

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!