[solved] sed/grep Ersatz , wenns um mehr als ne Zeile geht ?

  • Tach Leutz


    Irgendwie find ich nix "Elegantes" , wie sich Teile eines Textes filtern lassen , der mit einem Schlüsselwort beginnt und einem Anderen endet , aber leider über eine beliebige Anzahl von Zeilen gehen kann .


    sed/grep sind da ja nicht wirklich zu gebrauchen - wenn ich nich einfach nur blind und/oder begriffsstutzig bin :whatever


    Scripten allein reicht leider nicht , da Sonderzeichen verloren gehen können ...


    Jemand ne Idee oder Tip ?


    HJS

    Working VDR : VDR-1.4.6 - ACPI/NVRAM Wakeup - working on hjslfs

    Einmal editiert, zuletzt von hjs ()

  • Hi HJS,


    Zitat

    Original von hjs
    Jemand ne Idee oder Tip ?
    HJS


    Ich benutz ja für solche Sachen immer wieder gerne awk, Gewohnheit eben...
    Perl würde sich auch anbieten, aber oft lassen sich probleme mit einem kleinen stückchen awk-code lösen und damit eben auch in ein script integrieren.


    Hier ein kleines Beispiel. Geht sicher noch kompakter, aber so isses übersichtlicher... :)


    BTW: verkraftet soweit ich weiss auch Steuerzeichen...

    cu -HD-

    VDR1 (stable),
    yavdr 0.3: POV330 ION, 3GB, OCZ Vertex2 60GB, DD Octopus 1xDuoFlexS2

  • Noch ne kleine Kurzanleitung zum Beispiel:


    BEGIN {} - dieser Code wird ausgeführt bevor mit der eigentlichen Verarbeitung begonnen wird.


    END {} - dieser Code wird ausgeführt nachdem die eigentlichen Verarbeitung beendet wurde.


    Alle anderen Code-Stücke werden auf jede Zeile angewendet, auf die der "Selektor" passt.


    // {} - die beiden Slashes am Anfang sagen, dass dieser Code auf alle Zeilen angewendet wird (das zwischen den Slashes soll eine regex sein... :) ).


    /anfang/ {} - dieser Code wird nur auf Zeilen angewendet, in denen der String "anfang" vorkommt


    /ende/ {} - dito nur mit "ende"


    Die regex, die ich jetzt heir verwendet habe sind natürlich sehr trivial. Man kann dort auch komplexeres definieren. Was regex halt so hergibt...


    In den Klammern gibts dann die Möglichkeit mit dem Inhalt der Zeile was zu machen, z.B. print (Ausgabe) von $0 (der ganzen Zeile). Es gibt noch weitere Build-in Variables, die aber alle in der awk-manpage ganz gut dokumentiert sind.

    cu -HD-

    VDR1 (stable),
    yavdr 0.3: POV330 ION, 3GB, OCZ Vertex2 60GB, DD Octopus 1xDuoFlexS2

  • Zitat

    Original von Holger D.
    BTW: verkraftet soweit ich weiss auch Steuerzeichen...


    Scheinbar fast alles , außer dem / , abba da gibbet ja Mittel und Wege :)


    Das Ergebnis sieht schon recht gut aus - Thx again :]


    HJS

  • Zitat

    Original von Holger D.
    Noch ne kleine Kurzanleitung zum Beispiel:
    [...]


    Yeah - das hilft :)


    Zitat


    Es gibt noch weitere Build-in Variables, die aber alle in der awk-manpage ganz gut dokumentiert sind.


    Hehe - da sollte ich mir ne deutsche Übersetzung suchen , sonst lauf ich mit meinem begrenzten Englisch Vokabular direkt vor die Wand .


    Abba die Kurzanleitung langt für meine Zwecke ... :tup


    HJS

  • Zitat

    Original von hjs
    Hehe - da sollte ich mir ne deutsche Übersetzung suchen , sonst lauf ich mit meinem begrenzten Englisch Vokabular direkt vor die Wand .


    Vielleicht wird dir HIER etwas geholfen :arme

    VDR1: AMD Duron-1300, 512mb RAM, Nexus-S rev2.1, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    VDR2: Athlon XP-M-2600+, 512mb RAM, TT Prem 1.3 DVB-S, Skystar2, Airstar 2, Debian Lenny, kernel: 2.6.28-etobi.3, VDR 1.6.0-17 experimental/extensions von Tobi
    Extern: Activy300, Gen2VDR V2

  • Ok, damit hier sed nicht ganz zu kurz kommt: Ein wenig sed-Magie. Sed kann durchaus auch mit mehrzeiligen Textpassagen arbeiten, auch wenn manches doch ein wenig Grübeln erfordert.


    Ausgehend von folgendem Text:

    Code
    eins xxx 1
    zwei xxx 2
    drei xxx 3
    vier xxx 4
    fünf xxx 5
    sechs xxx 6
    sieben xxx 7

    kann man so z.b. nur in den Zeilen drei bis vor sechs eine Aktion durchführen:

    Code
    /^drei/ {
      :loop
      s/xxx/***/
      n
      /^sechs/!b loop
      }

    Die dazu gehörige Ausgabe:
    eins xxx 1
    zwei xxx 2
    drei *** 3
    vier *** 4
    fünf *** 5
    sechs xxx 6
    sieben xxx 7



    Will man dagegen richtig zeilenübergreifend arbeiten, kann man auch mehrere Zeilen zusammen sammeln:

    Code
    /^drei/ {
      :loop
      N
      /\nsechs/!b loop
      s/drei.*sechs/drei-bis-sechs/g
      }

    Die dazu gehörige Ausgabe:
    eins xxx 1
    zwei xxx 2
    drei-bis-sechs xxx 6
    sieben xxx 7


    Weitere interessante Spielmöglichkeiten bietet der 'hold space', ein Zwischenspeicher, in dem man einige Zeilen zwischenlagern kann, für spätere Verwendung:

    Code
    /^drei/h
    /^sechs/ {
      x
      G
      s/^drei\(.*\)\nsechs\(.*\)/drei-bis-sechs\1\2/
      }

    Die dazu gehörige Ausgabe:
    eins xxx 1
    zwei xxx 2
    drei xxx 3
    vier xxx 4
    fünf xxx 5
    drei-bis-sechs xxx 3 xxx 6
    sieben xxx 7


    Und noch ein letzter: Kann man wohl die Zeilen drei und sechs vertauschen? Man kann:

    Die dazu gehörige Ausgabe:
    eins xxx 1
    zwei xxx 2
    sechs xxx 6
    vier xxx 4
    fünf xxx 5
    drei xxx 3
    sieben xxx 7



    Sed ist halt weit mächtiger, als es auf den ersten Blick scheint. Viel Spaß beim weiteren Experimentieren!



    Gruß,


    Udo

  • Hrs - entweder is mein Zuckerspiegel zu weit unten oder die Linse noch Äthanol getrübt :whatever


    Nee - Thx für die Tips , aber ich denke , um aus


    Code
    bla-schwall-brabbel
    sülz-und tu<hier-gehts-los>Das-ist
    der-text
    den-ich-gern
    hätt<hier-ist-ende>abba-leider-kommt
    noch-weiteres-Gerümpel<hier-gehts-los>auch-das-will-ich-haben<hier-ist-ende>


    das


    Code
    Das-ist
    der-text
    den-ich-gern
    hättauch-das-will-ich-haben


    zu machen , ist ersma awk und auf das Zwischenergebnis sed die geschickteste Wahl .
    Oder sed im awk ? Naja - Experimentieren werd ich :)


    HJS

  • So lange es pro Zeile nur einen solchen Text gibt, ist das noch recht einfach:

    Code
    /<hier-gehts-los>/!d
    s/.*<hier-gehts-los>//
    :loop
    /<hier-ist-ende>/ !{
      N
      b loop
      }
    s/<hier-ist-ende>.*//


    Nach dem letzten s/ kann man dann sogar noch weiter mit dem erkannten Block arbeiten.


    Leider legt sich der Code auf die Nase, wenn mehrere interessante Blöcke in einer Zeile sind. (Stichwort greedy matching.)
    Da wäre es dann schon das einfachste, in einem Vorlauf erst mal vor <hier-gehts-los> und nach <hier-ist-ende> zusätzliche Zeilenumbrüche einzubauen.


    Gruß,


    Udo

Jetzt mitmachen!

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