[Gelöst] Text in {Klammern} ändern/entfernen?

Smalltalk
Antworten
Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [Gelöst] Text in {Klammern} ändern/entfernen?

Beitrag von Meillo » 10.02.2020 16:29:50

hikaru hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 15:51:22
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 15:08:14
Nun zum interessanten Teil, was das sed-Programm macht.

Code: Alles auswählen

/^{\([0-9][0-9]*\) .*}$/s//-\1-/
Es besteht aus nur genau einem Befehl, naemlich dem `s'-Befehl. Das vor dem `s' ist eine Adresse in Form eines regulaeren Ausdrucks, der bestimmt auf welche Zeilen in der Eingabe der s-Befehl angewendet werden soll.
Gibt es einen Grund, warum du diese Schreibweise gewählt hast, und nicht die in meinen Augen verbreitetere?:

Code: Alles auswählen

's/^{\([0-9][0-9]*\) .*}$/-\1-/'
Diese Schreibweise fuehrt die Ersetzung in allen Zeilen durch, wobei die meisten davon scheitern werden. Meine Variante fuehrt sie nur in den Zeilen aus, in denen sie erfolgreich sein wird. Das ich sinngemaess zutreffender das was man eigentlich haben will und weniger der Holzhammeransatz. Im Endeffekt macht es keinen Unterschied, ich finde das eine nur logisch passender, darum verwende ich es eher (was aber nicht heisst, dass ich deine Variante nicht oft genug ebenso verwenden wuerde).
Weiterhin könnte man das Pattern logisch vereinfachen, jetzt da wir wissen, dass es führende Nullen gibt:

Code: Alles auswählen

^{\([0-9]\+\) .*}$
... aber nur wenn man die nicht-POSIX-Erweiterung `-E' verwendet. Historisch und nach POSIX kann sed nur BREs und die kennen kein `+'.

Regex sind wie Abseits. Entweder hat man verstanden wie sie funktionieren, oder nicht.
Den Abseits-Vergleich finde ich nicht ganz treffend, aber ich verstehe was du sagen willst. Die zwei Hauptgruende, warum die Leute keine REs koennen sind:

1) Sie versuchen es gleich gar nicht, weil sie vom kryptischen (d.h. ungewohnten) Aussehen abgeschreckt sind.
2) Sie koennen nicht stupide genug Parser spielen.

REs zu lesen wird einfach, sobald mal sein Vermutungs-Hirn abschaltet und stupide Regeln abarbeitet. So viele Regeln sind es bei REs gar nicht. (EREs sind IMO die einfachste weil einheitlichste Variante; PCREs haben den meisten Schickschnack.)

Wenn man REs schnell lesen koennen will, dann muss man, wie auch beim Grundschullesenlernen und beim Programmierenlernen, sich ein Pattern-Matching aneignen. Man muss Strukturen erkennen lernen ... auf einen Blick sehen was zusammen gehoert und was separate Teile sind. Ausserdem in welchem Kontext sich etwas befindet. So ist ein Stern beispielsweise fast immer ein Quantifier fuer das was davor steht, ausser er ist escapet oder steht in einer Zeichenklasse, dann ist er literal aufzufassen.

Das ist von der Herausforderung nichts anderes als die Lateinische Schrift oder eine Handschrift oder Suetterlin oder Chinesische Schriftzeichen lesen zu lernen. Der identische Vorgang, gleich einfach oder schwierig -- ganz wie man es bewerten will -- nur dass REs eine sehr viel kleinere Sprache mit weniger Regeln sind als all die anderen.

Lord_Carlos hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 15:22:16
Spricht sed nicht den gleichen syntax wie regex in z.B. Javascript, java oder python?
Im Prinzip ja, aber ... ;)

... Ich glaube, die Inkompatibilität beruht auf zwei Umständen:
1. Verschiedene Rexex-Implementationen nutzen verschiedene Erweiterungen.
2. Die Escaping-Regeln unterscheiden sich zwischen den Implementationen.
War es nicht Knuth der meinte:
Unix is 14 different kinds of regular expressions living under one roof.
Ganz falsch liegt er damit nicht. ;-)

Es gibt verschiedene Varianten von REs, bekannt sind beispielsweise die BREs und EREs von POSIX und PCRE von Perl. Das sind aber nur Standardisierungen, also die Dokumentation von Gemeinsamkeiten von Implementierungen. Dann gibt es noch die Implementierungen, die den Standards aehneln, aber Abweichungen enthalten.

Sed verwendet normalerweise BREs, kann aber mit `-E' (bei GNU sed) um ein paar ERE-Funktionen erweitern, aber eben nicht kompatibel, weil in EREs das Plus unescapet die Sonderbedeutung hat, waehrend es bei gsed nur escapet die Sonderbedeutung hat. Da kollidieren eben die Historie von sed (+ ist literal) mit der Grundidee von EREs (jedes escapte Zeichen ist literal).

Dieses Wirrwarr zu durchschauen ist wirklich schwer.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [Gelöst] Text in {Klammern} ändern/entfernen?

Beitrag von Meillo » 10.02.2020 16:40:33

eggy hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:11:39
Aber klar lassen die sich erklären, sehr gut sogar, allerdings wird's wesentlich einfacher, wenn man dazu nen kleinen Abstecher in die Theoretische Informatik macht :mrgreen:
Da hast du natuerlich Recht. Es geht aber auch auf einem praxisbezogeneren Ansatz wenn man auf Friedl's Buch (O'Reilly) zurueckgreift. Selten gibt es Themen bei denen man genau ein Buch lesen muss um alles dazu zu lernen und zu verstehen was noetig ist. Das Buch ist ein Meisterwerk, wie ich finde. (Nicht in der Art wie Kernihans oder Knuths Buecher Meisterwerke sind, sondern in einer weniger kunstvollen Art, ungehobelter, praktischer, aber nicht weniger ein Meisterwerk.)
Use ed once in a while!

Benutzeravatar
hikaru
Moderator
Beiträge: 13594
Registriert: 09.04.2008 12:48:59

Re: [Gelöst] Text in {Klammern} ändern/entfernen?

Beitrag von hikaru » 10.02.2020 17:05:50

Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:29:50
Diese Schreibweise fuehrt die Ersetzung in allen Zeilen durch, wobei die meisten davon scheitern werden. Meine Variante fuehrt sie nur in den Zeilen aus, in denen sie erfolgreich sein wird. Das ich sinngemaess zutreffender das was man eigentlich haben will und weniger der Holzhammeransatz.
Danke! Bedeutet das dann, dass deine Variante performanter ist - wenn man z.B. nicht auf 200 sondern auf 200 * 10^6 Zeilen arbeiten würde?
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:29:50
... aber nur wenn man die nicht-POSIX-Erweiterung `-E' verwendet. Historisch und nach POSIX kann sed nur BREs und die kennen kein `+'.
Sowas hatte ich schon befürchtet. Ich finde das Thema POSIX vs. irgendwelche *ismen spannend, aber ich komme leider/zum Glück nur recht selten mit der reinen Lehre in Kontakt und muss mir sowas daher auch nicht merken.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:29:50
Wenn man REs schnell lesen koennen will, dann muss man, wie auch beim Grundschullesenlernen und beim Programmierenlernen, sich ein Pattern-Matching aneignen. Man muss Strukturen erkennen lernen ... auf einen Blick sehen was zusammen gehoert und was separate Teile sind. Ausserdem in welchem Kontext sich etwas befindet.
Noch ein einfaches Grundschulbeispiel: Prioritätsregeln bei Grundrechenarten (inklusive Klammersetzung). Das ist sogar strukturell schon recht nahe an Regex.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:29:50
So ist ein Stern beispielsweise fast immer ein Quantifier fuer das was davor steht, ausser er ist escapet oder steht in einer Zeichenklasse, dann ist er literal aufzufassen.
Ja, Literale sind ein notwendiges, aber zum Glück kleines Übel. Unglücklich finde ich die Kontextsensitivität des Zirkumflex. Wenn einen sowas anspringt muss man immer erst nachschauen, ob eckige Klammern in der Nähe sind um eine Vorstellung zu entwickeln, was hier passiert.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:29:50
Sed verwendet normalerweise BREs, kann aber mit `-E' (bei GNU sed) um ein paar ERE-Funktionen erweitern, aber eben nicht kompatibel, weil in EREs das Plus unescapet die Sonderbedeutung hat, waehrend es bei gsed nur escapet die Sonderbedeutung hat. Da kollidieren eben die Historie von sed (+ ist literal) mit der Grundidee von EREs (jedes escapte Zeichen ist literal).

Dieses Wirrwarr zu durchschauen ist wirklich schwer.
In der Tat:

Code: Alles auswählen

$ cat test.txt
{123 abc}
{4 def}
$ sed -E 's/^\{([0-9]+) .*\}$/-\1-/' test.txt
-123-
-4-
Ich weiß gerade nicht, ob das deine Aussage untermauert, oder ihr widerspricht. :roll:

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [Gelöst] Text in {Klammern} ändern/entfernen?

Beitrag von Meillo » 10.02.2020 17:39:25

hikaru hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:05:50
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 16:29:50
Diese Schreibweise fuehrt die Ersetzung in allen Zeilen durch, wobei die meisten davon scheitern werden. Meine Variante fuehrt sie nur in den Zeilen aus, in denen sie erfolgreich sein wird. Das ich sinngemaess zutreffender das was man eigentlich haben will und weniger der Holzhammeransatz.
Danke! Bedeutet das dann, dass deine Variante performanter ist - wenn man z.B. nicht auf 200 sondern auf 200 * 10^6 Zeilen arbeiten würde?
Ich glaube nicht, denn die RE muss ja in beiden Faellen fuer alle Zeilen getestet werden. In meinem Fall um zu sehen, ob der s-Befehl angewendet werden soll; in deinem Fall um ihn anzuwenden. Vielleicht ist deine Variante sogar schneller, falls das Matchingergebnis bei mir naemlich nicht gecacht wird, muss die RE beim s-Kommando nochmal angewendet werden.

Wenn du's schneller haben willst, dann schaffst du das vielleicht, wenn du mit einer ersten einfachen RE (ohne Klammern und mit wenig Backtrackingpotenzial) eine Vorauswahl triffst und nur auf die Kandidaten dann die volle RE loslaesst. Wenn dadurch aber zu oft die RE abgewechselt wird, koennte das je nach Implementierung auch wieder Zeit kosten ...

Die Zeitperformance interessiert mich aber, wie du weisst, nicht besonders.

hikaru hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:05:50
Unglücklich finde ich die Kontextsensitivität des Zirkumflex. Wenn einen sowas anspringt muss man immer erst nachschauen, ob eckige Klammern in der Nähe sind um eine Vorstellung zu entwickeln, was hier passiert.
Der hat sogar drei Bedeutungen:

1) Am Anfang der RE matcht er auf den Zeilenbeginn
2) Am Anfang einer Zeichenklasse negiert er das Set
3) Ueberall sonst steht er literal

Wahrscheinlich sind fuer mich REs einfach schon so normal, dass mir das gar nicht mehr auffaellt. Im Deutschen stoere ich mich ja auch nicht daran, dass der Punkt das Satzende markiert oder eine Abkuerzung anzeigt oder ein Ordinalpunkt ist oder ein Tausendertrenner oder ein ``...'' ... ;-) Man gewoehnt sich an alles.

Und aus der Praktikersicht: Je mehr Sonderzeichen zu verwendest, desto eher kollidierst du mit anderen Sprachen in deinem Umfelde (sh, sed, awk, ...). Darum ist es manchmal besser Zeichen wiederzuverwenden. Nicht jede Entscheidung war gut, so haette ich beispielsweise das Ausrufezeichen zur Zeichenklassennegation besser gefunden (wie in der Shell). Dass man `^' im Text (wo er niemals ein Zeilenanfangsmarker sein kann) nicht escapen muss, finde ich gut. Solche Designentscheidungen sind schwierig gut abzuwaegen. Es gibt viele Einfluesse, und teilweise bewerten wir die Situation heute im Hinblick auf Sachverhalte, die erst zwanzig Jahre nach der urspruenglichen Designentscheidung entstanden sind. (Das ist ein echter Vorteil der kurzlebigen Informatik: Man muss sich gar nicht um ein dauerhaft tragfaehiges Design bemuehen.) Trotz all der RE-Durcheinanders haben die Unix-Typen es doch immer noch erstaunlich gut hinbekommen. All das lebt ja immer noch ... nach 50 Jahren!
Use ed once in a while!

Benutzeravatar
hikaru
Moderator
Beiträge: 13594
Registriert: 09.04.2008 12:48:59

Re: [Gelöst] Text in {Klammern} ändern/entfernen?

Beitrag von hikaru » 10.02.2020 18:29:39

Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
hikaru hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:05:50
Unglücklich finde ich die Kontextsensitivität des Zirkumflex. Wenn einen sowas anspringt muss man immer erst nachschauen, ob eckige Klammern in der Nähe sind um eine Vorstellung zu entwickeln, was hier passiert.
Der hat sogar drei Bedeutungen:

1) Am Anfang der RE matcht er auf den Zeilenbeginn
2) Am Anfang einer Zeichenklasse negiert er das Set
3) Ueberall sonst steht er literal
3. hatte ich schon wieder ausgeblendet. ;)
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Im Deutschen stoere ich mich ja auch nicht daran, dass der Punkt das Satzende markiert oder eine Abkuerzung anzeigt oder ein Ordinalpunkt ist oder ein Tausendertrenner oder ein ``...'' ... ;-) Man gewoehnt sich an alles.
Also ich stehe regelmäßig vor einem Fragezeichen, ob ein Satz, der mit einer Abkürzung endet, nur einen Punkt kriegt oder zwei.
Wenn er nur einen bekommt, worauf bezieht der Punkt sich dann und wo bleibt der andere? Wenn der Satz zwei Punkte bekommt, muss/darf der Zweite dann geplenkt werden? Und wenn er nicht geplenkt wird, woher weiß ich dann, ob der Satz tatsächlich zuende ist, oder ob da der dritte Punkt für eine unvollständiuge Aussage fehlt und ich mich auf die Suche nach der Fortsetzung machen sollte. :?

À propos "Fragezeichen":
Ich finde die spanische Variante, Fragen und Ausrufe nicht nur mit einem ? bzw. ! zu beenden, sondern auch mit einem ¿ bzw. ¡ einzuleiten, nett. Da weiß man gleich am Satzanfang, was jetzt kommt.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Nicht jede Entscheidung war gut, so haette ich beispielsweise das Ausrufezeichen zur Zeichenklassennegation besser gefunden (wie in der Shell).
Ja, das fände ich auch besser. Eigentlich scheint ja das Ausrufezeichen das univererselle Negationszeichen zu sein. Allerdings frage ich mich dann, warum Pascal dafür <> verwendet.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Dass man `^' im Text (wo er niemals ein Zeilenanfangsmarker sein kann) nicht escapen muss, finde ich gut. Solche Designentscheidungen sind schwierig gut abzuwaegen.
Ich verstehe was du meinst. Der Nachteil ist halt, dass man ein literales ^ am Zeilenanfang doch wieder escapen muss, womit es wieder kontextsensitiv wird. Das wird z.B. interessant, wenn man Regex-Pattern aus mehreren Variablen zusammensetzt, die zweite Variable mit einem ^ beginnt, der Inhalt der Ersten an dieser Stelle aber nicht bekannt ist.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Das ist ein echter Vorteil der kurzlebigen Informatik: Man muss sich gar nicht um ein dauerhaft tragfaehiges Design bemuehen.
Das hat sich mein ehemaliger Chef auch gedacht, als er vor rund 40 Jahren anfing, die Software zu schreiben, mit der ich im Kern immer noch arbeite. Lass es mich so sagen: Ich hätte es nett von ihm gefunden, wenn er damals schon an solche Sachen gedacht hätte, wie dass das 20. Jahrhundert irgendwann mal vorbei ist. ;)

Benutzeravatar
Meillo
Moderator
Beiträge: 8818
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: [Gelöst] Text in {Klammern} ändern/entfernen?

Beitrag von Meillo » 10.02.2020 19:04:48

hikaru hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 18:29:39
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Im Deutschen stoere ich mich ja auch nicht daran, dass der Punkt das Satzende markiert oder eine Abkuerzung anzeigt oder ein Ordinalpunkt ist oder ein Tausendertrenner oder ein ``...'' ... ;-) Man gewoehnt sich an alles.
Also ich stehe regelmäßig vor einem Fragezeichen, ob ein Satz, der mit einer Abkürzung endet, nur einen Punkt kriegt oder zwei.
Diese Frage kann ich dir beantworten: Korrekte Rechtschreibung ist ein Punkt. Wenn ein Satz(inhalt) schon mit einem Punkt endet wird *kein* weiterer Punkt hinzugefuegt.
Wenn er nur einen bekommt, worauf bezieht der Punkt sich dann und wo bleibt der andere?
Das verstehe ich gut. Wir Informatiker denken halt in Strukturen. Die Nicht-Informatische Welt um uns herum tut das nicht. Die denken mehr in Oberflaechlichkeiten. (Das soll gar nicht so sehr werten, es ist einfach eine andere Betrachtungsweise, die andere Vorteile hat.) So wird in der Typographie beispielsweise nicht unterschieden ob der abschliessende Punkt innerhalb oder ausserhalb der Anfuehrungsstriche steht. Fuer mich gibt es beide Faelle und ich will bewusst den einen oder den anderen waehlen koennen. Du willst ebenfalls Klarheit haben und zum Ausdruck bringen koennen, ob ein Punkt einen Satz beendet oder nicht. Das sollte bestenfalls der Punkt selbst aussagen koennen, oder eben mit moeglichst wenig Kontext.

Kuerzlich habe ich eine sogenannte Hundertertafel aus dem Matheunterricht der Grundschule gesehen. Da stehen in einem 10x10-Raster alle Zahlen von 1 bis 100 drauf. Das sieht dann so aus:

Code: Alles auswählen

 1  2  3  4  5  6  7  8  9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
...
Fuer mich als Informatiker ist das schwer ertraeglich. In meinem Verstaendnis korrekt waere:

Code: Alles auswählen

 0  1  2  3  4  5  6  7  8  9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
...
Dann gibt es naemlich eine Zeile fuer alle Zahlen mit der 1 vorne, und eine mit den Zahlen mit der 2 vorne. Bei dem was sie aber tatsaechlich lehren muessen sie schon mit Ausnahmen und Sonderfaellen anfangen, die nicht noetig waeren.

Die Einordnung der Informatik als Strukturwissenschaft finde ich passend. Genau darum geht es in ihr IMO in erster Linie: Strukturen zu erkennen, zu gestalten, die inneren Strukturen zu finden, in Strukturen zu denken.

Aber mit so einem Ansatz kann man die Welt um uns herum nicht erklaeren. Da frustriert man sich bloss.

À propos "Fragezeichen":
Ich finde die spanische Variante, Fragen und Ausrufe nicht nur mit einem ? bzw. ! zu beenden, sondern auch mit einem ¿ bzw. ¡ einzuleiten, nett. Da weiß man gleich am Satzanfang, was jetzt kommt.
Das gefaellt mir auch.

Viel wichtiger waere es mir aber wenn wir im Deutschen von den vertauschten Zehnern und Einern bei der Aussprache der Zahlen wegkommen wuerden. Das ist so schrecklich wie das US-Amerikanische Datumsformat mit den vertauschten Monaten und Tagen. :facepalm:
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Nicht jede Entscheidung war gut, so haette ich beispielsweise das Ausrufezeichen zur Zeichenklassennegation besser gefunden (wie in der Shell).
Ja, das fände ich auch besser. Eigentlich scheint ja das Ausrufezeichen das univererselle Negationszeichen zu sein. Allerdings frage ich mich dann, warum Pascal dafür <> verwendet.
In der Unix-Welt und allem was sie gepraegt hat (was so ziemlich alles ist) ist das der Fall, aber Pascal ist eine Parallelwelt und ebenso alt. Ausserdem verwendet auch SQL `<>' und das ist auch aus der Zeit. `!' fuer ``Nicht'' ueberzeugt mich, aber `<>' hat auch seine Logik, die ich ebenso ansprechend finde.
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Dass man `^' im Text (wo er niemals ein Zeilenanfangsmarker sein kann) nicht escapen muss, finde ich gut. Solche Designentscheidungen sind schwierig gut abzuwaegen.
Ich verstehe was du meinst. Der Nachteil ist halt, dass man ein literales ^ am Zeilenanfang doch wieder escapen muss, womit es wieder kontextsensitiv wird.
... aber mit einer Optimierung fuer wenig Escaping bei den ueblichen Faellen.
Das wird z.B. interessant, wenn man Regex-Pattern aus mehreren Variablen zusammensetzt, die zweite Variable mit einem ^ beginnt, der Inhalt der Ersten an dieser Stelle aber nicht bekannt ist.
Und darum finde ich die EREs (egrep, awk, usw.) so gut. Bei denen wird jedes Zeichen das escapet ist literal gesehen. Du kannst also ganz einfach alle Zeichen der Variable escapen und kannst damit literal matchen. Bei BREs (sed, grep, ...) geht sowas nicht.

Meillo hat geschrieben: ↑ zum Beitrag ↑
10.02.2020 17:39:25
Das ist ein echter Vorteil der kurzlebigen Informatik: Man muss sich gar nicht um ein dauerhaft tragfaehiges Design bemuehen.
Das hat sich mein ehemaliger Chef auch gedacht, als er vor rund 40 Jahren anfing, die Software zu schreiben, mit der ich im Kern immer noch arbeite. Lass es mich so sagen: Ich hätte es nett von ihm gefunden, wenn er damals schon an solche Sachen gedacht hätte, wie dass das 20. Jahrhundert irgendwann mal vorbei ist. ;)
;-)


(Wir schweifen ganz schoen ab ... Vielleicht sollte ein Mod bald mal spitten. ;-) )
Use ed once in a while!

Antworten