[Bash] Array-Inhalt mit grep weiterverarbeiten

  • Hi,


    ich habe eine Inputdatei. Die formatiere ich etwas um. Und zwar in ein Array, weil ich ungerne temporäre Dateien schreiben möchte.


    Ich möchte nur aus dem Array nur die Elemente, welche einen bestimmten Text enthalten.


    Bei normalen Dateien würde man das einfach mit Grep machen.


    Der Versuch mit:
    echo ${array[*]} | grep "irgendwas"


    schlägt aber fehlt. Es kommt immer das gesamte Array heraus.
    Der Grund ist mir klar geworden, als ich das grep weggelassen habe und mal nur das Array echoed habe. echo gibt den Array-Inhalt nicht zeilenweise aus sondern hängt alle Elemente einfach hintereinander.


    Wie gebe ich den Array-Inhalt zeilenweise aus?
    Eine Schleife drehen wollte ich eigentlich vermeiden, weil das ja auch nicht gerade schnell ist.


    Grüße

  • Hallo!


    Ganz ohne Schleife gehts wohl nicht, aber es ist möglich für die ganze Schleife nur einmal grep aufzurufen:


    Code
    for i in ${!array[@]}
    do
        echo "${array[$i]}"
    done | grep "irgendwas"

    Noch schneller läuft das ganze, wenn du auf grep verzichtest:


    Code
    for i in ${!array[@]}
    do
        [[ "${array[$i]}" =~ "irgendwas" ]] && echo "${array[$i]}"
    done

    Ziemlich übler Bashism, aber es läuft ;)


    Grüße
    Sebastian

    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

    Einmal editiert, zuletzt von lubot ()

  • Zitat

    Original von HTPC-Schrauber
    ich habe eine Inputdatei. Die formatiere ich etwas um. Und zwar in ein Array, weil ich ungerne temporäre Dateien schreiben möchte.


    Wie wär's mit perl:

    Perl
    #!/usr/bin/perl
    
    
    open (FILE, "<meineDatei") or die "Fehler!\n";
    my @array = <FILE>;
    foreach my $line (grep (/irgendwas/, @array)){
      print ($line."\n");
    }
    exit(0);


    HTH...


    Dirk

  • Zitat

    Original von lubot

    Code
    for i in ${!array[@]}
    do
        [[ "${array[$i]}" =~ "irgendwas" ]] && echo "${array[$i]}"
    done


    Das klappt leider nicht. Weil dann der ganze Inhalt übereinstimmen müsste. Incl. Gross/Klein. Oder irre ich?


    Was macht ${!array[@]} ?


    d.heinrichs: Hmm, würde auch gehen. Allerdings wollte ich ungerne Perl und Bash mischen. Und das Script macht insgesamt noch ne ganze Menge mehr als nur das. Dementsprechend wärs wohl geschickter wenn ich bei einer Sprache bleibe. Trotzdem danke.

  • Hallo,


    also wenn Du Dein Script auch noch nach nem Jahr Pause verstehen willst, würde ich nicht die Bash-Syntax bis aufs letzte ausreizen, sondern eher etwas konventioneller (langsamer?) bleiben:

    Bash
    #!/bin/bash
    pattern="what ever"
    
    
    for line_nr in $(seq 0 $((${#array[@]} - 1))); do
       tmp=`echo ${array[$line_nr]} | grep "$pattern"`
       if [ "x$tmp" != "x" ]; then
          echo $tmp;
       fi   
    done


    Gruß Geronimo


    P.S. ich persönlich würde array noch in all_lines oder so umbenennen ;)

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

  • EDIT: geronimos Ansatz mit eingefügt.


    ${!array[@]} wird zu 0, ..., ${#array[@]}
    Also im Fall unten 0, 1, 2


    Nein es muss nicht der ganze Inhalt übereinstimmen. Du kannst aber anstatt "eins" auch .*eins.* schreiben.



    Gibt folgendes aus:


    Du brauchst für die Regex mindestens Bash 3.1.

    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

    Einmal editiert, zuletzt von lubot ()


  • Das geronimos Schleife so langsam ist liegt nicht am seq, sonder daran, dass in jedem Schleifendurchgang, also für jede Zeile einzeln, grep aufgerufen wird. Das kostet. Bei der anderen Schleife wird grep, nachdem die Schleife komplett durchgelaufen ist, aufgerufen. Also nur einmal.

    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

    Einmal editiert, zuletzt von lubot ()

  • Danke lubot für die harten Fackten.


    Das der Unterschied so groß ist, hat mich auch überrascht. Ist doch immer gut, mal ne Messung einzuschieben!
    Also wenn der Bezug zu den gefundenen Zeilen irrelevant ist, würde ich den ersten Vorschlag von lubot nehmen. Das ist ein guter Kompromiss aus Lesbarkeit und Geschwindigkeit.
    Ansonsten muss man wohl oder übel zur zeilenbasierten Verarbeitung greifen.
    Wenn man den bashismus gut kommentiert, sollte man auch wieder reinfinden können ;)


    Gruß Geronimo

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

  • Welche von den vieren meinst du?

    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

  • Nö, die Schleifen sind alle ok.


    Aber pattern-matching mit Bash würde ich schon nimmer als Grundwissen einstufen. Das ist schon "Oberstufen-Wissen". Kann natürlich sein, dass das für Dich kalter Kaffee ist. Bei mir ist es so, dass ich vielleicht alle halbe Jahr mal ein bisschen tiefer ins Bashwissen eintauchen muss.
    Wenn ich da nach nem halben Jahr meine eigenen Werke anschaue, muss ich schon etwas grübeln.


    Wenn Du das Problem nicht hast, ist ja gut :)

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

  • Ich hab jetzt diese Version genommen:

    Zitat

    for i in ${array[*]}
    do
    echo "$i"
    done | grep "irgendwas"


    Einfacher und funktioniert genauso.


    Das Ding ist natürlich Teil eines sehr viel größeren Scripts. Das Script hat schon mehr was mit Programm zu tun. Aber gut. Ich benutze da auch noch den OSDServer um ein VDR-Menü zu erzeugen.
    Wenns fertig ist wird es hier im Forum im EPGData2VDR-Thread zu finden sein.


    Das Kontrukt oben kommt da drin jedenfalls mehrfach vor. Zusätzlich noch mit cut garniert.


    Insgesamt kann ich meinen eigenen Code aber nachher schon auch wieder lesen. Also so übel scheints nicht zu sein.


    Jedenfalls danke ich vielmals für die ausgiebige Hilfe und Beratung.

  • Zitat

    Originally posted by HTPC-Schrauber
    Der Versuch mit:
    echo ${array[*]} | grep "irgendwas"


    schlägt aber fehlt. Es kommt immer das gesamte Array heraus.


    Da kann man aber durchaus was daraus machen, man muss nur noch etwas dazu geben:



    ... ergibt ein Array mit nur noch 3 Elementen, nämlich "1 2 3" "4 a b" "f 5 6".



    Gruß,


    Udo

Jetzt mitmachen!

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