Zeichen ersetzen
Zeichen ersetzen
Ich möchte via script drei Zeichen, sagen wir a,b,c in einer Textdatei komplett durch sagen wir x, y, z ersetzen, also jedes a durch x, jedes b durch y und jedes c durch z ersetzen. Wie macht man das, möglichst in einem Durchgang? Ich nehme an, sed muss benutzt werden, aber bisher habe ich keine Anleitung gefunden, die ich zweifelsfrei auf meine Aufgabe beziehen konnte.
Grüße, Günther
Grüße, Günther
Re: Zeichen ersetzen
Sed kann, muss aber nicht.
Wenn es Dir nur um 1:1 Ersetzungen geht, nimm tr, das ist in so einfachen Fällen leichter zu benutzen.
Wenn es Dir nur um 1:1 Ersetzungen geht, nimm tr, das ist in so einfachen Fällen leichter zu benutzen.
Code: Alles auswählen
cat datei.txt | tr 'abc' 'yxz'
Re: Zeichen ersetzen
Danke für den Versuch, funktioniert aber nicht. In der vorliegenden Form des Kommandos wird jedes zu ersetzende Zeichen durch das letzte im Ersatzstring ersetzt.
Re: Zeichen ersetzen
Komisch. Hier sieht das so aus:
Code: Alles auswählen
$ echo "abc abc acb bca cba" && echo "abc abc acb bca cba" | tr 'abc' 'xyz'
abc abc acb bca cba
xyz xyz xzy yzx zyx
Re: Zeichen ersetzen
Hmm, ich hätte wohl sagen sollen, dass die Zeichen als einzelne auftreten. Konkret geht's z.B. um typografische Anführungszeichen (gibt's wohl nur im Deutschen?), die bei jedem Auftauchen ersetzt werden sollen. Zum Testen so: "Gänsefüsschen unten" sollen, wo immer sie auftauchen, durch ein 'x', "Gänsefüßchen oben" durch ein 'y' ersetzt werden. Später weder natürlich die typografischen durch die international(?) gebräuchlichen Anführungszeichen ersetzt.
Ob's bei drei Zeichen bleibt, weiß ich noch nicht, aber wenn ich's bei dreien geschafft habe, werde ich das wohl erweitern können.
Ob's bei drei Zeichen bleibt, weiß ich noch nicht, aber wenn ich's bei dreien geschafft habe, werde ich das wohl erweitern können.
Re: Zeichen ersetzen
Dass es nicht geklappt hat, liegt da eher an den Anführungszeichen. tr ist für ganz einfache Sachen super, bei komplizierterem teilweise leider nicht, hätt ich vielleicht erwähnen sollen, sorry.
Versuchs mal damit:
Ich nehm als Trenner gerne den Unterstrich, liest sich m.E. besser, in vielen Tutorials wirst Du ein Minus an der Stelle finden, dadurch nicht verwirren lassen.
Edit: nach dem letzten Semikolon kannst Du weitere Pattern der Form s_was_gegenwas_g; einfügen, das s steht dabei für ersetzen und das g für global, also nicht nur den ersten Treffer.
Versuchs mal damit:
Code: Alles auswählen
echo "„123“ 321" | sed "s_„_a_g; s_“_b_g; "
Edit: nach dem letzten Semikolon kannst Du weitere Pattern der Form s_was_gegenwas_g; einfügen, das s steht dabei für ersetzen und das g für global, also nicht nur den ersten Treffer.
Re: Zeichen ersetzen
Danke sehr!
Mich verwirren weniger die Unterstriche, als die beiden "normalen" Anführungszeichen beim sed, deren Bedeutung mir noch unklar ist.
Unabhängig davon versuch' ich mal, mein Verständnis in menschlicher Sprache zu formulieren:
s bedeutet etwa "ersetz' was"
die "Gänsefüßchen unten" geben das "was" an, das ersetzt werden soll: ergo: sind das zu ersetzende Zeichen.
a ist das Ersatzzeichen
g sagt, dass "jedes" Vorkommen ersetzt werden soll
Das 1. Semikolon sagt: es kommt noch was
zwischen erstem und zweitem Semikolon steht dann die nächste Komplett-Ersetzung von "Gänsefüßchen oben" zu b
Was sagt das 2.Semikolon?
Warum das Ganze in Anführungszeichen?
Auf eine Datei angewendet scheint es nach erstem Test in dieser Form zu funktionieren:
Ich hatte allerdings in test.txt nur einen kurzen einzeiligen Text mit einmaligem Vorkommen der typografischen Anführungszeichen stehen.
Grüße, Günther
Mich verwirren weniger die Unterstriche, als die beiden "normalen" Anführungszeichen beim sed, deren Bedeutung mir noch unklar ist.
Unabhängig davon versuch' ich mal, mein Verständnis in menschlicher Sprache zu formulieren:
s bedeutet etwa "ersetz' was"
die "Gänsefüßchen unten" geben das "was" an, das ersetzt werden soll: ergo: sind das zu ersetzende Zeichen.
a ist das Ersatzzeichen
g sagt, dass "jedes" Vorkommen ersetzt werden soll
Das 1. Semikolon sagt: es kommt noch was
zwischen erstem und zweitem Semikolon steht dann die nächste Komplett-Ersetzung von "Gänsefüßchen oben" zu b
Was sagt das 2.Semikolon?
Warum das Ganze in Anführungszeichen?
Auf eine Datei angewendet scheint es nach erstem Test in dieser Form zu funktionieren:
Code: Alles auswählen
sed "s_„_a_g; s_“_b_g; " test.txt
Grüße, Günther
Re: Zeichen ersetzen
Das zweite Semikolon ist überflüssig, ausser Du willst danach noch ein drittes Pattern anfügen.
Die Anführungszeichen kann man oftmals weglassen, aber wenn Du mehrere Pattern hintereinander benutzt, kann es Dir passieren, dass die Shell denkt, das Semikolon sei die Beendung des Befehls und es folgt ein normaler Befehl für sie und nicht, dass das folgende auch noch für sed sei. Ich hab mir irgendwann einfach angewöhnt sowas im Zweifelsfall einfach mitzutippen.
Die Anführungszeichen kann man oftmals weglassen, aber wenn Du mehrere Pattern hintereinander benutzt, kann es Dir passieren, dass die Shell denkt, das Semikolon sei die Beendung des Befehls und es folgt ein normaler Befehl für sie und nicht, dass das folgende auch noch für sed sei. Ich hab mir irgendwann einfach angewöhnt sowas im Zweifelsfall einfach mitzutippen.
Re: Zeichen ersetzen
Super!
Jetzt wird's noch einen Tick haariger: Langer Bindestrich. Den krieg ich im Terminal gar nicht eingegeben und auch wenn ich das sed-Kommando scripte, den langen Bindestrich reinkopiere, wird der bei der Ausführung offenbar nicht als zu ersetzend erkannt.
Grüße, Günther
Jetzt wird's noch einen Tick haariger: Langer Bindestrich. Den krieg ich im Terminal gar nicht eingegeben und auch wenn ich das sed-Kommando scripte, den langen Bindestrich reinkopiere, wird der bei der Ausführung offenbar nicht als zu ersetzend erkannt.
Grüße, Günther
Re: Zeichen ersetzen
https://de.wikipedia.org/wiki/Halbgeviertstrich ?
Bei mir kann ich den direkt in die Shell kopieren (im Browser einfach nur markieren, in der Konsole dann mit der mittleren Maustaste einfügen), ob das auch bei Dir geht, hängt von Windowmanager, Terminal, Shell, Mondphase, etc ab.
Falls nicht, die entsprechende UTF-8 Codierung nehmen und es mal damit versuchen.
Und falls das auch nichts wird, warten bis Meillo vorbei liest, der kennt sich da besser aus
Bei mir kann ich den direkt in die Shell kopieren (im Browser einfach nur markieren, in der Konsole dann mit der mittleren Maustaste einfügen), ob das auch bei Dir geht, hängt von Windowmanager, Terminal, Shell, Mondphase, etc ab.
Falls nicht, die entsprechende UTF-8 Codierung nehmen und es mal damit versuchen.
Code: Alles auswählen
echo 1 | sed s_1_–_g;
echo 1 | sed s_1_$'\u2013'_g;
Re: Zeichen ersetzen
Gedankenstriche – machst du mit AltGr+-. Der hat dann die Länge von ½-em. Allerdings gibt es dann noch den doppelt so langen Gedankenstrich —, Den Bindestrich, Den Bindestrich, der nicht trennt, den waagrechten Strich, den Gedankenstrich ohne feste Länge, den ASCII Gedanken-/Beindestrich...
Ich nehme an, du verwendest 2 verschiedene.
Ich nehme an, du verwendest 2 verschiedene.
rot: Moderator wanne spricht, default: User wanne spricht.
Re: Zeichen ersetzen
Hallo wanne!
Ich will keine "langen" Bindestriche "machen"/malen, sprich setzen, ich will sie ersetzen, was immer für *Geviert*-Striche das sein mögen.
Danke eggy, das hilft wieder weiter. Die verlinkten Seiten hatte ich bereits eingesehen. Jetzt bemerke ich, dass auch utf-8-Nummern dort angegeben werden. Da ich die Zeichen als solche bisher weder via Tastatur noch Kopieren in mein sed-Kommando/Script hineinbekommen habe, werde ich es mit den Nummern versuchen.Für meine Zwecke müsste ich dein zweites Kommando wohl "umdrehen", also: - richtig?
Ich will keine "langen" Bindestriche "machen"/malen, sprich setzen, ich will sie ersetzen, was immer für *Geviert*-Striche das sein mögen.
Danke eggy, das hilft wieder weiter. Die verlinkten Seiten hatte ich bereits eingesehen. Jetzt bemerke ich, dass auch utf-8-Nummern dort angegeben werden. Da ich die Zeichen als solche bisher weder via Tastatur noch Kopieren in mein sed-Kommando/Script hineinbekommen habe, werde ich es mit den Nummern versuchen.Für meine Zwecke müsste ich dein zweites Kommando wohl "umdrehen", also:
Code: Alles auswählen
s_$'\u2013'_1
Zuletzt geändert von guennid am 03.02.2019 15:11:36, insgesamt 1-mal geändert.
Re: Zeichen ersetzen
Was ersetzt werden soll vorne, wodurch ersetzt werden soll dahinter - ggfs das g für global nicht vergessen.
Und ausprobieren wäre schneller gegangen als fragen
Und ausprobieren wäre schneller gegangen als fragen
Re: Zeichen ersetzen
Nur, wenn ich richtig lag.Und ausprobieren wäre schneller gegangen als fragen
Ich bin nicht so für Schnelligkeit, mehr für "Sicherheit"/Umständlichkeit.
Wird nix.
Das hier habe ich erfolglos versucht:
sed "s_$'\u2013'_+_g; " test.txt. Ich kriege bei wikipedia nur eine weitere UTF-8-Nummer, die sich zweifelsfrei einem dieser "Gedankenstriche" zuordnen ließe, u. zwar in der Form: U+2014. Wie kriege ich raus, welches utf-8-Zeichen definitiv in meinem Beispieltext steckt?
-
- Beiträge: 385
- Registriert: 16.06.2017 09:52:36
Re: Zeichen ersetzen
Ich würde folgendes Vorgehen vorschlagen:
Den Gedankenstrich habe ich in LibreOffice erzeugt und ins Terminal kopiert (urxvt). Du kannst auch den UTF-8-Code auf mehreren Websites im Internet nachschauen. Dort findest Du dann auch die (englischen) Namen für das entsprechede Zeichen (z.B. "EN DASH" in diesem Fall).
Umgekehrt kann z.B. printf auch aus Unicode-Codes Zeichen machen (s. manpage von printf).
EDIT: Ist mir noch eingefallen: Wahrscheinlich unterstützen nicht alle Varianten von sed hex-Zeichen. Ich nutze GNU sed aus stretch.
Bei meinem sed und meinem Terminal geht sogar:
Code: Alles auswählen
$ echo '–' | hd
00000000 e2 80 93 0a |....|
00000004
$ echo '–' | sed "s_\xe2\x80\x93_+_g"
+
Umgekehrt kann z.B. printf auch aus Unicode-Codes Zeichen machen (s. manpage von printf).
EDIT: Ist mir noch eingefallen: Wahrscheinlich unterstützen nicht alle Varianten von sed hex-Zeichen. Ich nutze GNU sed aus stretch.
Bei meinem sed und meinem Terminal geht sogar:
Code: Alles auswählen
$ echo '–' | sed "s_–_+_g"
+
Re: Zeichen ersetzen
Das mit den Tastatureingaben, bzw copy+paste ist halt so'ne Sache, je nachdem wo du was eintippst. Giuckst du hier (1). Ich habe inzwischen vier solcher für mich kritischen Zeichen entdeckt und kann die auch via copy+paste mit sed händeln. eggys Schnipsel ist da schon was sehr Geeignetes. Aber schöner wäre halt, man könnte dem sed einen eindeutigen utf-8-code zum Ersetzen mitgeben statt das, was man da zu sehen glaubt, z.B. einen "Gedankenstrich", was immer der jeweilige Leser für einen solchen halten mag, hier also AltGr+-, bzw Strg+shift+2013, eingegeben im Terminal (übrigens das gleiche das du benutzt].
Und da war eggys Syntax wohl nicht die zielführende. Aber Meillo interessiert''s vielleicht nicht.
(1) viewtopic.php?f=12&t=171239&hilit=utf+8
Und da war eggys Syntax wohl nicht die zielführende. Aber Meillo interessiert''s vielleicht nicht.
(1) viewtopic.php?f=12&t=171239&hilit=utf+8
Re: Zeichen ersetzen
Warum machst du das denn nicht?Aber schöner wäre halt, man könnte dem sed einen eindeutigen utf-8-code zum Ersetzen mitgeben statt das, was man da zu sehen glaubt
Suche dir den Code fuer die Zeichen raus, beispielsweise von dieser Seite:
https://www.utf8-chartable.de/unicode-u ... pl?utf8=0x
und packe dir fuer jeden langen oder kurzen Bindestrich den Wert in eine
Variabel.
Mit sed kannst du diese dann zusammenfassen und mit nur einem Ersatzeichen
austauschen.
Einfacher geht es nicht.
Ein Beispiel, quick and dirty:
Code: Alles auswählen
#!/usr/bin/env bash
A=$(printf "\xE2\x96\x88")
B=$(printf "\xe2\x98\x8e")
C=$(printf "\xe2\xa8\x81")
D=$(printf "\x5e")
E=$(printf "\x22")
# usw.
echo $A $B $C $D $E # Zeige Variableninhalt
text="ab-█-⨁-☎-cd ^ef-█-g" # Testtext
sed "s/[$A$B$C]/*/g;s/\\$D/\\$E/g" <<<$text # Zeichenersetzung
### Ergebnis: ab-*-*-*-cd "ef-*-g
# Erklaerung:
# s/[$A$B$C]/*/g => Suche (zusammengefasst) bestimmte Sonderzeichen und ersetze
# alle Vorkommen mit nur einem anderem Zeichen (hier mit Stern).
# s/\\$D/\\$E/g => Suche Circumflex accent und ersetze mit Quotation mark.
# Quotation mark Variabel und aehnliche muessen gesondert escaped werden
# (Doppelter backslash).
# sed string muss in Quotation marks gesetzt werden, damit die Shell die
# Variabel(n) expandieren kann.
Re: Zeichen ersetzen
aus einem "meiner Schnipsel":guennid hat geschrieben:03.02.2019 19:25:32eggys Schnipsel ist da schon was sehr Geeignetes. Aber schöner wäre halt, man könnte dem sed einen eindeutigen utf-8-code zum Ersetzen mitgeben statt das,
Was das \u2013 bedeutet, findet man übrigens da: https://en.wikipedia.org/wiki/List_of_U ... de_symbols
Re: Zeichen ersetzen
Den Meillo interessiert's gerade nicht, weil die technische Loesung schon vorliegt.
Das ist der Knackpunkt beim Verstaendnis. Dein Wunsch (``was immer der jeweilige Leser fuer einen solchen halben mag'') ist natuerlich unmoeglich, weil woher soll die Software wissen, was derjeweilige Leser fuer einen haelt? Was die Software am ehesten in diese Richtung bieten koennte, waeren Aequivalenzklassen in denen alle Gedankenstriche, die der jeweilige Sprachraum (!) fuer solche haelt, zusammengefasst werden, aber ob das in den Locales umgesetzt ist, weiss ich nicht (ich vermute eher, dass nicht). Folglich bleibt dir nur, selber genau aufzulisten, welche Unicode-Codepoints (Zeichen) du ersetzen willst und die mittels UTF-8-Escape anzugeben. Das haben die anderen schon vorgeschlagen ... darum kann ich mich hier gemuetlich zuruecklehnen und mitlesen.guennid hat geschrieben:03.02.2019 19:25:32einen "Gedankenstrich", was immer der jeweilige Leser für einen solchen halten mag
Use ed once in a while!
Re: Zeichen ersetzen
Teilweise/Vielleicht kann man hier auf die Hilfe von uconv und co zurückgreifen, ich find die jedoch nicht wirklich intuitiv.Meillo hat geschrieben:04.02.2019 06:06:11Was die Software am ehesten in diese Richtung bieten koennte, waeren Aequivalenzklassen in denen alle Gedankenstriche, die der jeweilige Sprachraum (!) fuer solche haelt, zusammengefasst werden, aber ob das in den Locales umgesetzt ist, weiss ich nicht (ich vermute eher, dass nicht).
Daher lieber selbst die paar in Frage kommenden Zeichen rausfischen:
Code: Alles auswählen
sed 's_\(.\)_\1\n_g' datei.txt | grep -v "[a-z0-9A-Z,]" | sort -u
Alles was da übrigbleibt kann man dann in Ruhe in der Tabelle nachschlagen.
Oder es den Rechner machen lassen, ich bin dazu grad über uni2ascii gestolpert, das hat nen paar interessante Optionen in der manpage, für den Fall hier scheint U passend:
Code: Alles auswählen
echo – | uni2ascii -a U -q
Re: Zeichen ersetzen
Für mich ist das "technisch" nach wie vor nicht klar, denn das hier: funktioniert nicht. In test.txt steht nichts außer: Die Behandlung der typografischen Anführungszeichen ist erledigt, darum geht's nicht (mehr). Das fragliche Zeichen, der "lange" Bindestrich wird nicht umgewandelt. Ich sehe im Moment nicht, dass ich in meinem Umsetzungsversuch irgendeine Anmerkung von eggy auf S.1 nicht beachtet hätte.
Und ich weiß nach wie vor nicht, ob es das an einem Syntaxfehler in eggys Vorschlag liegt, oder ob das von mir als "langer" Bindestrich genannte Zeichen eben nicht das von eggy vermutete utf-8-Zeichen ist.
Ersetze ich im sed Kommando eggys utf-8-Konstrukt ($'\u2013') via Tastatureingabe: AltGr+- dann wird das Zeichen umgewandelt.
Same procedure mit
Code: Alles auswählen
sed "s_$'\u2013'_+_g; " test.txt
Code: Alles auswählen
William C. „Billy“ Irvine sollen – und zwar
Und ich weiß nach wie vor nicht, ob es das an einem Syntaxfehler in eggys Vorschlag liegt, oder ob das von mir als "langer" Bindestrich genannte Zeichen eben nicht das von eggy vermutete utf-8-Zeichen ist.
Ersetze ich im sed Kommando eggys utf-8-Konstrukt ($'\u2013') via Tastatureingabe: AltGr+- dann wird das Zeichen umgewandelt.
Same procedure mit
Code: Alles auswählen
$ echo 'William C. „Billy“ Irvine sollen – und zwar' | sed "s_$'\u2013'_+_g; "
Zuletzt geändert von guennid am 04.02.2019 19:41:31, insgesamt 1-mal geändert.
Re: Zeichen ersetzen
Das kann auch nicht funktionieren. Es ist auch nicht das was eggy vorgeschlagen hat. Du musst genau (!) hinschauen! (Tipp: Quoting)guennid hat geschrieben:04.02.2019 19:25:10Für mich ist das "technisch" nach wie vor nicht klar, denn das hier:funktioniert nicht.Code: Alles auswählen
sed "s_$'\u2013'_+_g; " test.txt
Use ed once in a while!
Re: Zeichen ersetzen
Versuchs mal ohne die ". Hier müssen die ausnahmsweise mal weg, weil $'\u...' ja durch die Shell ersetzt werden soll.
Code: Alles auswählen
echo 'William C. „Billy“ Irvine sollen – und zwar' | sed s_$'\u2013'_+_g
Re: Zeichen ersetzen
ad Meillo
Und du solltest weniger selektiv lesen.
Bingo, Herr eggy!!!
Und du solltest weniger selektiv lesen.
Bingo, Herr eggy!!!