Wie kann ich pro Aufruf die jeweils nächste Zeile einer Datei auslesen?

Dieses Thema im Forum "Shell-Skripte" wurde erstellt von franzjosef, 30.08.2008.

  1. #1 franzjosef, 30.08.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    Hallo zusammen,

    ich hoffe ihr könnt mir helfen. Und zwar bin ich auf der Suche nach einer Möglichkeit, wie man Zeilenweise aus einer Datei lesen kann.

    Am besten ich erkäre es an einem Beispiel.
    Ich möchte mit wget über mehrere Proxies Dateien herunterladen. Das DL-Skript habe ich schon, allerdings ohne Proxy-Funktion.

    Deshalb muss in dieses Bash-Skript eine Funktion, die mir aus einer Liste Proxy.txt den jeweils nächsten Aufruft. Sprich wenn der DL- fertig ist, dann wird danach die neue Funktion aufgerufen.

    Ich habe mir die neue Funktion wie folgt vorgestellt:
    Die Funktion liest aus der Proxy.txt die erste Zeile und schreibt mit
    Code:
    export http_proxy=111.111.111.111:8080
    
    den Proxy für wget. Damit die Funktion weiß, welche Zeile die Funktion beim letzten Aufruf genommen hat, merkt sich die Funktion die Zeile 1 in einer Variablen/Datei.
    Beim nächsten Aufruf schaut die Funktion, welche Zeile das letzte Mal benutzt wurde und benutzt die jeweils nächste.

    Sprich die Funktion liest die zweite Zeile und schreibt ein
    Code:
    export http_proxy=222.222.222.222:8080
    
    Wie könnte ich mein Vorhaben am besten bewerkstelligen?

    Viele Grüße
    Martin
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. caba_

    caba_ (caba{_,}|manuw)

    Dabei seit:
    07.08.2007
    Beiträge:
    334
    Zustimmungen:
    0
    Meinst du sowas:
    Code:
    while read i; do echo "WAS SOLL ICH MIT ${i} machen?"; done < proxyliste.txt
    Oder habe ich das doch falsch verstanden?
     
  4. #3 franzjosef, 30.08.2008
    Zuletzt bearbeitet: 30.08.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    also wenn ich deine zeile richtig interpretiere, dann wird ja für jede zeile was gemacht.

    die funktion, die ich bräuchte, soll nur bei bedarf ausgeführt werden.
    also nicht pro zeile in proxliste.txt soll was ausgeführt werden.

    Zur Erläuterung:
    wget kann ja nur mit einem Proxy umgehen. die Proxy-Adresse nimmt wget aus der variablen http_proxy

    Du kannst Dir vorstellen, dass wenn das skipt gestartet wird, dann wird die neue Funktion das erste mal aufgerufen. Bei diesem ersten Aufruf liest es die erste Proxy-Adresse und schreibt diese in die variable http_proxy.

    Dann kommen wir in eine Schleife.
    In der Schleife werden mit Wget nun mehrere Dateien heruntergeladen. Neben dem DL mit wget finden auch noch andere Prüfungen statt. Wenn nun diese Prüfung ergibt, dass der Proxy gewechselt werden muss, dann soll die neue Funktion das zweite Mal aufgerufen werden.

    Die Funktion soll nun die Variable http_proxy mit der zweiten Zeile aus der ProxyListe.txt belegen. Dazu muss die Funktion ja aber wissen, dass bei ihrem vorherigen Aufruf die Zeile 1 bereits benutzt wurde und nun eben die zweite Zeile dran ist.

    Danach macht die DL-Schleife weiter, bis wieder eine Bedingung eintritt, dann wird die Funktion erneut aufgerufen, die dann eben die dritte Zeile finden soll.

    usw.

    Viele Grüße
    Martin
     
  5. #4 dosenfleisch, 30.08.2008
    dosenfleisch

    dosenfleisch Foren As

    Dabei seit:
    29.03.2007
    Beiträge:
    75
    Zustimmungen:
    0
    Code:
    grep -A1 http_proxy=111.111.111.111:8080
    
     
  6. #5 Wolfgang, 30.08.2008
    Wolfgang

    Wolfgang Foren Gott

    Dabei seit:
    24.04.2005
    Beiträge:
    3.978
    Zustimmungen:
    0
    Ort:
    Erfurt
    Du kennst sed?
    Dort läßt sich direkt die Zeile, die ausgegeben werden soll, adressieren.
    Du musst also nur eine Variable hochzählen und diese dann sed als Adresse übergeben.


    BTW sieht dein Vorhaben irgendwie nach Verwendung von anonymen Proxys aus, um illegale Aktionen zu vertuschen. Ich las so eine ähnliche Anfrage schon einmal in einem Forum. Wenn das der Fall ist, rate ich dir, dich nicht in falscher Sicherheit zu wiegen.
    Das sind zu 99% nur falsch konfigurierte Proxys, die von jetzt auf gleich transparent werden. ;)
    Wenn nicht, setze meinen Gedanken einfach um.

    Wolfgang
     
  7. #6 franzjosef, 31.08.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    nein, leider nicht.
    wenn ich bisher was geskriptet habe, dann war das batch unter dos. da ich nun immer mehr linux-geräte im haus habe, muss ich mich da jetzt auch mal mit beschäftigen.
    in batch gibt es leider keinen befehl, der mir genau eine bestimmte zeile aus einer datei ausliest. das musste ich mir ganz umständlich selber bauen.

    wie würde denn mit sed die skript-zeile aussehen, um z.B. die 3. Zeile einer datei liste.txt in eine variable http_proxy zu schreiben?

    Viele Grüße
    Martin
     
  8. Yomm

    Yomm Foren As

    Dabei seit:
    12.08.2007
    Beiträge:
    79
    Zustimmungen:
    0
    Der Stream-Editor Sed ist aus der shell-Programmierung und wird folgendermassen beschrieben:
    sed ist ein relativ altes Tool.wird aber immer noch eingesetzt, etwa um Zeilen einer Datei oder eines Datenstromes zu manipulieren. Besonders haeufig und gern wird sed zum Suchen und Ersetzen von Zeichenfolgen verwendet.
    Na, das ist doch was.
    sed (adresse1),(adresse2) 'komanndo' (datei(en)::: Komando muss alles andere kann
    adrese1 = start/ adresse2 = Ende
    Ein ! hinter adresse1 und 2 bedeutet, das der Bereich von 1 bis 2 ausgeschlossen ist. Komanndo gilt also nur fuer den Rest. Mit -n wird der Default Output von sed abgeschaltet

    sed -n '4p' file.dat liest nur die 4. Zeile aus file.dat
    sed -n '4,7p' file dat liest Zeile 4 bis 7 . sed -n '7,4p' file dat wird ignoriert (Bis groesser als von = ruechwaerts lesen)

    Komanndo Bedeutung
    a (append) fuegt eine oder mehrere Zeilen an
    c (change) ersetzt die Zeile durche eine oder mehrere andere
    d (delete) loescht die Zeile
    g (get buffer) kopiert in temporeren Puffer
    G (getNewline) fuegt g an den Arbeitspuffer
    h (hold) Gegenteil von g -Kopiert G zu g
    H (HoldNewline) Gegenstueck zu G
    i (insert) fuegt zeile vor der selektierten zeile
    l (listing) zeigt nicht druckbare Zeichen an
    n (next) Verwendet das naechste Komanndo auf die
    naechste Zeile
    p (print) Gibt die Zeile aus
    q (quit) beendet sed
    r (read) Datei integrieren.liest Zeilen aus eine Datei ein
    s (substitut) Ersetzt eine Zeichenfoge
    x (XChange) vertauscht temporeren Puffer mit Arbeitspuffer
    y (yank) ersetzt ein Zeichen
    w (write) schreibt zeilen in einer Datei
    ! Negation: verwendet Komanndo auf andere Zeilen

    Sehen wir mal, ob Du damit etwas anfangen kannst
    Gruss
    Yomm
     
  9. #8 dosenfleisch, 31.08.2008
    dosenfleisch

    dosenfleisch Foren As

    Dabei seit:
    29.03.2007
    Beiträge:
    75
    Zustimmungen:
    0
    da du keine bestimmte, sondern jeweils die nächste zeile lesen willst, nochmal mein vorschlag mit grep.
    Code:
    newproxy=$(grep -A1 $oldproxy proxylist)
    echo $newproxy
    
    damit erhälst du immer den jeweils nächsten nach dem zuletztgenutzen proxy.

    erscheint mir am einfachsten
     
  10. #9 franzjosef, 31.08.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    stimmt mit
    Code:
    newproxy=$(sed -n '4p' list.txt)
    echo $newproxy
    
    list er mir die 4. Zeile aus der Datei list.txt, schreibt diese in die Variable newproxy und mit echo schreibt er mir auch das richtig auf den bildschirm.

    aber wenn ich hier schaue, müsste es dann nicht
    Code:
    newproxy=$(sed -n '/4/p' list.txt)
    heißen. Wie ist denn das mit den '/'-Zeichen?







    Hört sich für mich schon recht schön an, aber irgendwie mache ich doch wohl was falsch.

    Inhalt der Datei list.txt:
    Code:
    111
    222
    333
    444
    555
    
    dass ich die Variable oldproxy mit
    Code:
    oldproxy=111
    erst deklarieren muss, das habe ich nun herausgefunden. sonst läuft das ganze nicht. ich muss der Variablen auch den ersten Wert mitgeben, sonst läuft es auch nicht. Sprich ein
    Code:
    oldproxy=
    reicht leider nicht.

    Wenn ich nun ein
    Code:
    newproxy=$(grep -A1 $oldproxy list.txt)
    dann wird daraus aber immer nur ein
    Code:
    111 222
    
    Was soll denn dieses -A1 genau machen?


    Belege ich
    oldproxy=222
    dann hängt der Aufruf von
    Code:
    newproxy=$(grep -A1 $oldproxy list.txt)
    wieder

    Was mache ich falsch?

    Viele Grüße
    Martin
     
  11. #10 Wolfgang, 31.08.2008
    Wolfgang

    Wolfgang Foren Gott

    Dabei seit:
    24.04.2005
    Beiträge:
    3.978
    Zustimmungen:
    0
    Ort:
    Erfurt
    Hallo
    Also nochmal langsam:


    Das -A bei grep gibt dir den Treffer + die darauf folgende Zeile an.
    Insofern nicht das was du willst.
    Es sei denn, du verwendest es in einem Array und greifst auf den Index 1 zu. (was in der Bash geht)

    Dein Vorhaben ist mir ehrlich gesagt etwas suspect.
    Warum postest du nicht den Beispielcode, dann lässt sich das Ganze weniger abstrakt erklären.

    Code:
    sed -n '/4/p' -> matcht auf 4 und printet wenn gefunden
    sed -n '4p'  -> Gibt nur die Zeile 4 aus
    
    Siehst du den Unterschied?
    Zu deinem Problem:
    Du zählst einfach die Zeilen in einer Variablen, und wenn du die nächste Zeile brauchst, übergibst du sie sed als Adresse.
    Wobei du dann doppelte Hochkomma verwenden musst, damit diese von der Shell aufgelöst werden kann.

    Aber wie gesagt: Poste deinen Code hier und deine Fragen werden konkreter.

    Wolfgang
     
  12. #11 franzjosef, 02.09.2008
    Zuletzt bearbeitet: 02.09.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    Hallo,

    ehrlich gesagt versteh ich den Unterschied nicht. was meinst Du mit matcht?

    Hier mal mein Pseudo-Code von dem, was ich brauche:

    Code:
    proxyline=1
    
    do
    export http_proxy=$(http://[sed -n ($proxyline)p proxylist.txt])
    echo $http_proxy
    echo $proxyline
    proxyline=$(($proxyline+1))
    
    if proxylist.txt is eof then proxyline=1
    
    while [proxylist.txt is not eof]
    
    done
    
    Sprich am Anfang wird ein Zähler proxyline erst mal auf 1 initialisiert.
    Dann läuft das ganze in eine Schleife. Solange nicht das Ende der Datei proxylist.txt erreicht ist, soll folgendes passieren.

    In der Datei proxylist.txt stehen ip-Adressen in der Form
    111.111.111.111:9999
    222.222.222.222:8888

    Nun soll pro Schleifendurchlauf die Variable http_proxy belegt werden.
    Die Variable muss dabei im erstn Schleifendurchlauf wie folgt belegt werden:

    http://111.111.111.111:9999

    Im zweiten Durchlauf soll folgender Wert angenommen werden:

    http://222.222.222.222:8888

    usw.

    Nachdem die Variable belegt ist, wird für mich erst einmal zur Kontrolle die Werte für die beiden Variablen ausgegeben.
    Dann wird der Zähler proxyline eins hochgesetzt.

    Ich dachte mir nun, dass ich die Variable wie folgt zusammenbaue.
    1. zuerst das fixe http://
    2. mit sed -n '@p' proxylist.txt die ip-Adresse + den Port auslese, wobei @ für den Zähler, also die Variable proxylist steht
    3. das ganze dann komplett in die Variable http_proxy schreibe

    Wenn eof erreicht wird, soll der Zähler wieder auf 1 gesetzt werden, damit es wieder von vorne losgeht, sprich die while-Schleife soll eine Endlosschleife sein.

    Was muss ich da tun, damit das funktioniert?

    Viele Grüße
    Martin
     
  13. #12 Wolfgang, 02.09.2008
    Wolfgang

    Wolfgang Foren Gott

    Dabei seit:
    24.04.2005
    Beiträge:
    3.978
    Zustimmungen:
    0
    Ort:
    Erfurt
    Das bedeutet, wenn in der Zeile eine 4 vorkommt, dann wird diese ausgegeben. Dass das nicht zwangsläufig die vierte Zeile ist, ist wohl klar.



    Grausam ...
    Dich erstmal mit den Grundlagen der Bash oder was immer du verwendest auseinandersetzen.

    Hier ein Link Klick und lesen

    Besonders für dich interessant:
    Schleifen, Redirect, Incrementierung von Variablen, sed

    Wir sind hier keine Scriptfabrik, deshalb nur die nötigen Werkzeuge:

    Code:
    i=1;
    for URLS in $(cat deine_urlliste);
    do
    
    ((i++)); # i hochzählen
    MY_PROXY='http://'$(sed -ne "${i}p" LISTE_DER_PROXYS);
    ...
    echo "$MY_PROXY"
    ...
    wget ....
    done
    
    Ob du den Proxy wechseln willst oder nicht, kannst du vor dem Increment von i ja testen.
     
  14. #13 franzjosef, 02.09.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    Gar nicht schlecht die Übersicht. Ein gutes Nachschlagewerk.

    Ich komme aus der DOS-Welt, da ist doch einiges anders. Aber da bei mir immer mehr Geräte mit Linux als Betriebssytem Einzug halten, muss ich mich auch mal mit bash beschäftigen.

    Wie nennt man sowas hier:

    Code:
    test() {
    echo test
    }
    
    Ist das eine Funktion oder heißt das Sprungmarke wie in einer Batch?

    Wenn ich nun aus so einer Funktion/Sprungmarke eine andere Aufrufe und diese zweite ist beendet, springt er dann wieder an den Aufruf in der ersten funktion zurück?

    Bsp.:

    Code:
    Funktion1(){
    echo "Ich bin da"
    Funktion2
    echo "bin wieder zurueck in Funktion1"
    }
    
    Funktion3(){
    echo "bin jetzt in f3"
    }
    
    Funktion2(){
    echo "wie gehts dir"
    }
    
    Funktion4(){
    echo "Funkion4"
    }
    
    Werden solche Funktionen eigentlich im Ablauf des skripts eigentlich ausgeführt oder nur dann, wenn sie explizit aufgerufen werden?

    Ich weiß, viele Anfängerfragen. Aber jeder hat mal angefangen.

    Viele Grüße
    Martin
     
  15. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  16. #14 Wolfgang, 02.09.2008
    Wolfgang

    Wolfgang Foren Gott

    Dabei seit:
    24.04.2005
    Beiträge:
    3.978
    Zustimmungen:
    0
    Ort:
    Erfurt
    Hallo

    Bevor ich jetzt Dinge wiederhole, die schon von Anderen aufgeschrieben wurden:
    Lies Kapitel 8

    Funktionen werden vorher definiert, oder per source aus anderen Initscripten in den Namensraum geholt.
    DOS Batch ist im Gegensatz zur Shell unter *nix eine Hilfskrücke.
    Wenngleich es auch da wenige Akrobaten unter Programmierern gab/gibt.

    Gruß Wolfgang
     
  17. #15 franzjosef, 02.09.2008
    Zuletzt bearbeitet: 03.09.2008
    franzjosef

    franzjosef Grünschnabel

    Dabei seit:
    30.08.2008
    Beiträge:
    9
    Zustimmungen:
    0
    Hallo Wolfgang,

    so bin wieder ein Stückchen weiter. Das mit dem sed ist aber kompliziert.
    Irgendwie ist mir da nicht so einfach, wann welche Klammer gesetzt werden muss und wann das Hochkomma und wann die Gänsefüßchen hermüssen.

    An Klammern gibt es ja drei Stück
    ()
    []
    {}
    Das mit den geschweiften Klammern, das taucht hier gar nicht erst auf.

    In der Doku steht auch, dass es keinen Unterschied macht, ob man das Hochkomma oder die Gänsefüßchen verwendet. Aber irgendwie glaube ich, dass dem nicht so ist.
    Kann es sein, dass wenn sich in dem Bereich etwas variables befindet (also entweder eine Variable (wie oben z.B. das i), dass man dann besser die Gänsefüßchen nimmt?

    Hier mal mein Zwischenergebnis:
    Code:
    Durchlauf=1
    proxyline=1
    
    # Schleife bricht ab, wenn Durchlauf <= 20
    while [ $Durchlauf -le 20 ] ; do
            echo "Durchlauf hat jetzt den Wert $Durchlauf"
    		
    lastProxy=$(wc -l <proxylist.txt)
    
    if ["$proxyline" -lt "$lastProxy"]; then
    	http_proxy='http://'$(sed -ne "${proxyline}p" proxylist.txt);
    	proxyline=$(($proxyline+1));
    	echo "$http_proxy"
    else
    	proxyline=1
    	http_proxy='http://'$(sed -ne "${proxyline}p" proxylist.txt);
    	proxyline=$(($proxyline+1));
    	echo "$http_proxy"
    fi
    		
            Durchlauf=$(($Durchlauf+1))
    done
    
    Irgenwo klemmt's noch. Kannst Du bitte mal schauen, wo ich den Fehler gemacht habe? Ist bestimmt nur wieder eine klammer oder so

    Viele Grüße
    Martin
     
Thema:

Wie kann ich pro Aufruf die jeweils nächste Zeile einer Datei auslesen?

Die Seite wird geladen...

Wie kann ich pro Aufruf die jeweils nächste Zeile einer Datei auslesen? - Ähnliche Themen

  1. [Python]Funktionsaufruf übergibt unbekannten Parameter

    [Python]Funktionsaufruf übergibt unbekannten Parameter: Hi, ich möchte eine Funktion der selben Klasse aufrufen und dabei Werte als Parameter übergeben, also self.<Funktionsname>(Parm1, ..., ParmN)...
  2. Wie kann ich dieses Fenster direkt aufrufen?

    Wie kann ich dieses Fenster direkt aufrufen?: Im Anhang seht Ihr eine Fenster welches ich direkt (evtl. Desktop-Verknüpfung) öffnen möchte. Ich möchte mich nicht immer durchklicken. Ideal...
  3. Kann ein C-Compiler C++-Aufrufe erzeugen?

    Kann ein C-Compiler C++-Aufrufe erzeugen?: Da manchen Foren lange Offtopic-Diskussion zuwider sind, wollte ich [THREAD=37341]hier[/THREAD] nicht weiter diskutieren, sondern zu einem neuen...
  4. Wie kann ich eine Konsole aufrufen?

    Wie kann ich eine Konsole aufrufen?: Hallo an alle, Ich habe seit gestern abend GRML 2.6.17 und Gnome 2.14 auf einem Laptop. Wie kann ich als Nicht-Root eine Konsole aufrufen?...
  5. LINUX (Ubuntu) Kann bestimmte Seite nicht aufrufen!

    LINUX (Ubuntu) Kann bestimmte Seite nicht aufrufen!: Hallo guten Abend zusammen::hilfe2: Ich habe seit kurzem Ubuntu (Linux) auf Laptop installiert. Ich kann aber leider bestimmte Websites...