Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

Antworten
Benutzeravatar
OsunSeyi
Hacker
Hacker
Beiträge: 392
Registriert: 27. Mai 2006, 01:28

sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von OsunSeyi »

Hallo,

Tut mir leid, der Titel ist ziemlich unverständlich...
Eigentlich eine ganz einfache Sache, darum ein Beispiel.

Der Übersichtlichkeit halber wähle ich nicht '/' sondern '|' als Trenner:

Code: Alles auswählen

sed 's|\(a\)b\+|\1c|g'
...wird mir bei 'ab' den String 'ac' liefern.

Und bei 'abb' natürlich ebenfalls 'ac' liefern, weil alle Vorkommen von 'b' durch ein 'c' ersetzt werden.

Ich möchte aber gerne alle Vorkommen von 'b' ersetzten, also 'acc' herausbekommen!
Das geht natürlich ganz einfach mit:

Code: Alles auswählen

sed 's|b|c|g'
Dies aber wiederum nicht in Abhängigkeit von dem vorausgehenden 'a'.
Das ist genau das Problem.

Ich arbeite mit einem Sed-File und würde es gerne auch mit sed hinbekommen...
abgdf
Guru
Guru
Beiträge: 3411
Registriert: 13. Apr 2004, 21:15

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von abgdf »

So?

Code: Alles auswählen

echo abb | sed 's/ab+/c/g'
Was machst Du bloß immer für Sachen? :)
Der Schrägstrich ("/") ist doch der normale Trenner für Suchen-/Ersetzen-Operationen. Nicht "|".

Übrigens wundere ich mich selbst, daß das funktioniert.
Eigentlich müßte

Code: Alles auswählen

ein "a" und eine beliebige Zahl "b"s
gesucht und durch ein "c" ersetzt werden. Das Ergebnis müßte nach meinem Verständnis daher eigentlich "c" sein, nicht "acc". Na ja. Ich vermeide deshalb RegEx, wo ich kann (meistens kann ich). Sonst kriegt man noch die "Zahnstocherkrankheit" (von den vielen "/ \..\ / /"). Das ist nicht gut für's Gehirn.

Hm, in Perl (meiner bevorzugten Sprache) hab' ich auch recht:

Code: Alles auswählen

echo abb | perl -e 'while(<>){s/ab+/c/g; print}'
ergibt "c".
Keine Ahnung, was sed sich da denkt.
Zuletzt geändert von abgdf am 19. Apr 2021, 22:31, insgesamt 1-mal geändert.
Benutzeravatar
OsunSeyi
Hacker
Hacker
Beiträge: 392
Registriert: 27. Mai 2006, 01:28

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von OsunSeyi »

Jupp, Regexe sind aber interessant 8)

Nicht, daß ich besonders bewandert wäre...

Das Plus muss maskiert werden mit '\+' und der Trenner ist eigentlich egal.
Wenn aber '/' im zu ersetzenden String vorkommt, muss halt ein anderes Zeichen genommen werden...

Aber das beantwortet leider nicht meine Frage, dabei denke ich das kann doch nicht so arg schwer sein. Habe aber bisher keine Lösung gefunden.
abgdf
Guru
Guru
Beiträge: 3411
Registriert: 13. Apr 2004, 21:15

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von abgdf »

OsunSeyi hat geschrieben: 19. Apr 2021, 22:30Das Plus muss maskiert werden mit '\+'
Ooh, bei den Perl-RegExes würde das bedeuten, daß tatsächlich nach einem "+" gesucht wird.
Offenbar unterscheiden sich Perl und sed hier zu sehr. Dann kann ich nicht mehr mithalten.
OsunSeyi hat geschrieben:Aber das beantwortet leider nicht meine Frage, dabei denke ich das kann doch nicht so arg schwer sein. Habe aber bisher keine Lösung gefunden.
Mein sed-Vorschlag funktioniert ja. Jetzt müßte man nur noch herausfinden, warum er funktioniert.
Benutzeravatar
OsunSeyi
Hacker
Hacker
Beiträge: 392
Registriert: 27. Mai 2006, 01:28

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von OsunSeyi »

Code: Alles auswählen

~ echo abb | sed 's/ab+/c/g'
abb # keine Ersetzung...

~ echo abbb | sed 's/ab+/c/g'
abbb # keine Ersetzung...

~ echo bbb | sed 's/ab+/c/g'
bbb # keine Ersetzung...

~ echo ab+ | sed 's/ab+/c/g'
c
Ähh... ja ersetzt 'ab+' und sonst nix, zumindestens bei mir!
Ich glaube aber nicht daß es sich verschieden verhält.

Code: Alles auswählen

~ echo ab | sed 's/ab\+/c/g'
c

~ echo abbbbbbbb | sed 's/ab\+/c/g'
c

~ echo b | sed 's/ab\+/c/g'
b # keine Ersetzung, passt nicht auf das Muster 'ab\+'
Was ich will ist:

Code: Alles auswählen

~ echo ab | sed ...
ac

~ echo abbb | sed ...
accc

~ echo db | sed ...
db  # keine Ersetzung weil kein vorangehendes 'a'
abgdf
Guru
Guru
Beiträge: 3411
Registriert: 13. Apr 2004, 21:15

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von abgdf »

Ich glaube, ich hatte mich verlesen. :ops: Weiß auch nicht, wie das passiert ist, aber ich hatte schon ziemlich viel Code geschrieben heute. Vielleicht flimmerten mir inzwischen die Buchstaben vor den Augen.
Du hast recht, was ich gepostet hatte, geht leider gar nicht.

Vielleicht geht das, was Du willst, nicht mit nur einer RegEx.
In Perl würde ich halt zweimal drübergehen:

Code: Alles auswählen

#!/usr/bin/perl

my $a = "abb";

if ($a =~ m/ab+/) {
    $a =~ s/b/c/g;
}
print "$a\n";
In sed kann ich Dir leider nicht helfen. :(
Benutzeravatar
Geier0815
Guru
Guru
Beiträge: 4465
Registriert: 14. Jun 2004, 09:12

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von Geier0815 »

Hmm, ich würde das Ganze ja sehr pragmatisch angehen: Matche auf ab und ersetze alle b durch c:

Code: Alles auswählen

sed '/ab/s/b/c/g'
Dies setzt aber voraus das keine weiteren b in der Zeile vorkommen, die nicht zu ab gehören. Evtl langt dir das ja so. Ansonsten kommen wir mMn in den Bereich der erweiterten RegEx wo wir dann mit so ekeligen Geschichten wie "matche auf a gefolgt von b(mindestens einmal vorkommend), schreibe diese ganzen b in einen anderen Stack, ersetze dort die b durch c, und schreibe zurück in den alten Ausdruck" arbeiten. Da bin ich mir aber auch nicht sicher wie man das macht und müßte wieder Bücher bzw Tutorials wälzen.
Dieses hier mag als vertiefender Einstieg dienen

Oder Du wartest bis robi das hier sieht und dann lernen wir alle noch etwas ;-)
Wenn Windows die Lösung ist...
kann ich dann bitte das Problem zurück haben?
Gräfin Klara
Hacker
Hacker
Beiträge: 667
Registriert: 23. Jun 2008, 20:51

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von Gräfin Klara »

OsunSeyi hat geschrieben: 19. Apr 2021, 22:42 Was ich will ist:

Code: Alles auswählen

~ echo ab | sed ...
ac

~ echo abbb | sed ...
accc

~ echo db | sed ...
db  # keine Ersetzung weil kein vorangehendes 'a'

Code: Alles auswählen

# sed '/^a/ s/b/c/g'
Benutzeravatar
Geier0815
Guru
Guru
Beiträge: 4465
Registriert: 14. Jun 2004, 09:12

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von Geier0815 »

@Gräfin Klara,

wo siehst Du nun den weltbewegenden Unterschied zu meiner Lösung? Du matchst auf a als erstes Zeichen ich auf ab. Trotzdem verhindert beides nicht das bei einem "ab xb" hinterher ein "ac xc" raus kommt da der match die ganze Zeile erfasst und die Option g für ein globales Ersetzen sorgt.
Wenn Windows die Lösung ist...
kann ich dann bitte das Problem zurück haben?
Benutzeravatar
OsunSeyi
Hacker
Hacker
Beiträge: 392
Registriert: 27. Mai 2006, 01:28

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von OsunSeyi »

Ja, es ist tatsächlich so nicht möglich.
Konkret geht es darum, aus plain Text Markdown zu erzeugen.

In Markdown gibt es keine geschützten Leerzeichen, wenn aber (in diesem Fall mit Pandoc) in Html konvertiert wird, können selbstverständlich mit '&nbsp;' Leerzeichen erzwungen werden.

Nun kann ich allerdings nicht pauschal alle Leerzeichen durch '&nbsp;' ersetzen, denn zB werden echte Leerzeichen in Markdown zum Erzwingen von Zeilenumbrüchen und zum Erzeugen von Listen und Codeblocks benötigt. Für diesen Fall kann ich aber zunächst Leerzeichen maskieren.

Als Beispiel wird '- Text' eine Liste erzeugen, '-&nbsp;Text' aber nicht.

Also ersetzte ich erst zu '-^Text', danach alle verbleibenen Leerzeichen zu '&nbsp;'
und danach 's/\^/ /g'. Das ist also nicht das Problem.

Aber 'normale' Leerzeichen zwischen einzelnen Worten durch '&nbsp;' zu ersetzen, sieht in Markdown so richtig sch... aus.

Also müsste ich erreichen, dass nur dann Leerzeichen durch '&nbsp;' ersetzt werden, wenn es mehr als eins ist. Also 's/ \+/ &nbsp;/g'. Dann aber bekomme ich natürlich immer nur ein '&nbsp;' egal wieviele Leerzeichen ich ersetzt haben will.

Oder auch hier maskieren mit 's/\(^ \) \(^ \)/\1^\2/g'
Aber welch ein Aufwand.

Und genau da liegt der Hase im Pfeffer.
Benutzeravatar
robi
Moderator
Moderator
Beiträge: 3204
Registriert: 25. Aug 2004, 02:13

Re: sed mehrfach-Ersetzung in Abhängigkeit von Ausdruck

Beitrag von robi »

Nimm mal das als Ansatz, vielleicht kommst du damit weiter.
Beruht auf einer Schleifenlösung

Code: Alles auswählen

# echo "ab abbb abbbb fbbb abbbbb" | sed ':a;s/\(ac*\)b/\1c/g;t a;'
ac accc acccc fbbb accccc
robi
Antworten