Anzeige:
Ergebnis 1 bis 6 von 6

Thema: sed: subpatterns nochmals substituieren?

  1. #1
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47

    sed: subpatterns nochmals substituieren?

    Hallo!
    Ich habe eine etwas kniffligere Anforderung an sed (oder awk?), die meinen derzeitigen Horizont auch vier Std. nächtlichem googlen übersteigt.

    Eingabe:
    In einem Text können beliebig verteilt Worte folgender genügsamen regulären Sprache vorkommen:
    Code:
    <a>.*</a>
    Also etwa
    Code:
    ...bla bla bla <a>foo.bar.baz</a> bla bla...
    Ausgabe:
    Daraus soll gemacht werden:
    Code:
    ...bla bla bla <a href="foo/bar/baz.html">foo.bar.baz</a> bla bla...
    Das Problem besteht darin, dass ein Subpattern einmal in einer veränderten Variante eingesetzt werden muss (Punkte durch Slashes substituiert).

    Das Resultat
    Code:
    ...bla bla bla <a href="foo.bar.baz.html">foo.bar.baz</a> bla bla...
    ist mit sed recht einfach durch
    Code:
    s/<api>\(.*\)<\/api>/<a href="\1.html">\1<\/a>/g
    zu erreichen.
    Auf die erste Einsetzung des Musters \1 müsste nochmal eine Substitution angesetzt werden, welche die Punkte durch Slashes ersetzt. Ich habe jedoch keine Ahnung, wie ich das erreichen kann.

    Ich bin für jede Idee dankbar!

  2. #2
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Hallo,

    wenn es nur um die Lösung der Aufgabe geht, dann würde ich sed einfach nochmal drüber laufen lassen (natürlich Such-/Ersetzungsmuster anpassen) oder zwei Ersetzungsausdrücke angeben ("s/.../;s/.../").

    Gruß, Florian
    Ein gebrechlich Wesen ist der X-Server.

  3. #3
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Hallo Florian,
    hmmm.... wie sähe dann das zweite Kommando aus? Ich habe auch kurz daran gedacht, aber den Gedanken sofort wieder verworfen, da ich nicht glaube, dass sich das mit sed noch lösen lässt. Andere a-Tags dürfen davon ja nicht beeinträchtigt werden. Ich finde die Stellen also niemals wieder! Abgesehen davon müssten auch die zwei Varianten (Wert von href und Text) unterschieden werden können und gleichzeitig Punkte durch Slashes substituiert werden (nur nicht der letzte von .html).

    Ich wüsste nicht wie das gehen soll.

    Grüße,
    Daniel

  4. #4
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    zuerst eine Warnung: Das Folgende funktioniert nur unter der Voraussetzung, dass das Muster "<api>...</api>" nur einmal pro Zeile auftaucht. Ich habe es auch nur mit einer Beispielzeile getestet, also gründlich prüfen!

    Die sed-Kommandofolge habe ich in ein Script ausgelagert, damit es übersichtlicher ist:
    Code:
    jan@jack:~/tmp> cat foobar.sed
    # Ersetzung wie im Original, aber beginnendes "<api" stehen lassen
    # damit haben wir noch einen Anhaltspunkt, wo zu ersetzen ist
    s/<api>(.*)<\/api>/<api href="\1.html">\1<\/a>/
    # Sprungmarke "L" definieren
    : L
    # Ersetzen des letzten, zwischen `<api href="` und `.html">` liegenden
    # . durch /
    s/(.*<api href="[^"]+)\.(.+\.html">)/\1\/\2/
    # wenn Ersetzung erfolgte: zurueck zur Sprungmarke "L"
    t L
    # keine Ersetzung mehr: Jetzt `<api href="` durch `<a href="` ersetzen
    s/<api href="/<a href="/
    jan@jack:~/tmp> echo 'bla bla <a href="a/b/c.html">a.b.c</a> bla <api>foo.bar.baz</api> bla bla' | \
    > sed -rf foobar.sed
    bla bla <a href="a/b/c.html">a.b.c</a> bla <a href="foo/bar/baz.html">foo.bar.baz</a> bla bla
    Wie Du siehst, habe ich die "-r"-Option des sed genutzt, damit wird das nicht so ein \-Verhau.

    Jan

  5. #5
    Registrierter Benutzer
    Registriert seit
    01.04.2009
    Ort
    Essen
    Beiträge
    25
    Zwar nicht sed sondern Perl, aber vielleicht ist es ja eine Option.

    Code:
    echo '...bla bla bla <a>foo.bar.baz</a> bla <a>heise.de</a>bla...' | perl -wpe 's{<a>(.*?)</a>}{($o,$n)=($1,$1);$n=~s#[.]#/#g; qq{<a href="$n">$o</a>} }ge'
    Kann auch ohne Probleme mit mehrere <a> auf einer zeile umgehen. Wenn das öffnen <a> und das schließen </a> auf unterschiedlichen zeilen steht dann geht es allerdiengs nicht. (Könnte man aber anpassen).

    damit wird das nicht so ein \-Verhau.
    Auch bei sed kann man andere Begrenzer als / wählen.
    Falsch zu liegen ist kein Misserfolg. Es sollte gefeiert werden, da die Erkenntnis etwas Falsch gemacht zu haben Verstehen und Erkenntnis auf ein neues Level anhebt.

  6. #6
    Registrierter Benutzer
    Registriert seit
    07.05.2007
    Beiträge
    656
    Moin,

    Zitat Zitat von Sid Burn Beitrag anzeigen
    Auch bei sed kann man andere Begrenzer als / wählen.
    Da das in diesem Fall ganze 2 (in Worten zwei) Backslashes einspart, habe ich drauf verzichtet. Wichtiger war mir die Übersichtlichkeit - d. h. Gruppierungen durch Klammern besser als solche erkennbar zu machen.

    Jan

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •