-
Ausgangspunkt dieser Untersuchung sind Erfahrungen mit den unix Editor-Programmen vi(m) und sed.
Schwerpunkt der jetzigen Untersuchung ist ein anderer Texteditor namens ed. Es geht in den folgenden Abschnitten nicht darum, ed als Texteditor der Wahl zu empfehlen, obwohl manche Systemadministratoren darauf schwören würden. Aus heutiger Sicht unter normalen Umständen zu sperrig. Aus ed gingen aber die Texteditors vi (über ex) und sed hervor. Diese Seite soll ein Verständnis für ed-s Eigenart vermitteln, das meines Erachtens das Erlernen der Texteditor-Familie (vi, ex, sed) erleichtert und beschleunigt. - Prinzipien des Texteditierens mit ed
ed ist ein zeilenorientierter Texteditor, der auf allen unixoiden Systemen vorinstalliert ist (Normalerweise unter /bin/ed). Es ist das älteste der hier untersuchten Tools: ed wurde von
Ken Thompson Anfang der 1970er Jahre geschrieben. Nicht nur im Hinblick auf die Chronologie, sondern auch im Hinblick auf Funktionalität und Bedienungskonzept, stellt ed die Grundlage dar. Im nächsten Abschnitt werden die wichtigsten Merkmale des Texteditors vorgestellt.
-
Will man interaktiv Datei DateiName bearbeiten, tippt man folgenden Befehl:
> ed DateiName
ed öffnen die Datei, überträgt den gesamten Dateiinhalt in den Speicher (editor's buffer), bewegt den Arbeitszeiger auf die letzte Dateizeile und zeigt die Gesamtzahl der Zeichen in der Datei auf.
> 3934 (In diesem Beispiel enthält die Datei 3934 Zeichen.)
Jede weitere Eingabe des Users versteht ed, als Aufforderung im Bezug auf das Editieren der Datei. Folgende Syntax gilt: [adress [, adress]] Befehl [Parameter] . Beachte: Der User bearbeitet nicht unmittelbar die Datei, sondern eine Kopie davon, den sogenannten Dateipuffer (Buffer): Jede Änderung, die nicht explizit gesichert (saved) wird, geht dementsprechend verloren.- Editiermodi:
Es gibt zwei Editiermodi: Befehl (Command) und Eingabe (Input).
- Im Befehlsmodus kann der Arbeitszeiger entlang der Datei bewegt werden, ein Zeichenmuster (Regular Expression) gesucht, ersetzt werden.
- Im Eingabemodus wird neuer Text eingetragen - hinzufügt (insert), anhängt (append), ersetzt (change).
- Textbezüge:
ed ist zeilenorientiert: Jede Aktion (Jedes Kommando) bezieht auf eine (ganzzahlige) Menge von Textzeilen. Eine Textzeile ist eine Zeichensequenz, die auf besondere Weise abgegrenzt wird.
- In unixoiden Betriebssystemen wird die Abgrenzung über das Trennzeichen das Linefeed, LF (ASCII-Code=10) gekennzeichnet.
- In Microsoft-Windows Betriebssystemen wird die Abgrenzung über die Zeichensequenz carriage return-Linefeed, CR (ASCII-Code=13) - LF (ASCII-Code=10) gekennzeichnet.
Der Bezug auf eine Zeile bzw. einen Zeilenbereich erfolgt nach verschiedenen Regeln:
- Impliziter Textbezug: Die einzelnen Befehle beziehen sich auf die laufende Zeile (wo sich der Arbeitszeiger gerade befindet).
- Expliziter Textbezug: Der User kann Zeile oder Zeilenbereich bestimmen (erweitern), worauf sich der Befehl bezieht. Dabei macht er sich den Adressierungsmechanismus von ed zunutze.
Wie definiert der User (Zeilen-)Adressen? Im einfachsten Fall ist die Adresse einer Zeile ihre Nummer im Puffer. Es gibt aber weitere Möglichkeiten auf eine bestimmte Zeile hinzuweisen
- Die erste Zeile hat die Nummer 1.
- Die Nummer 0 deutet auf die Zeile vor der ersten Zeile.
(Für den Befehl 'Füge neuen Text am Dateianfang ein', ist z.B. solche Möglichkeit unerlässlich.) - Die Letzte Zeile wird mit dem '$'-Zeichen adressiert.
- Das Zeichen '.' definiert die laufende Adresse.
- '+n' bedeutet Zeile '. + n' (n-te Zeile nach der laufenden Zeile).
Falls die Adressierung außerhalb des zulässigen Bereichs fällt, bleibt Alles beim Alten. - '-n' bedeutet Zeile '. - n' (n-te Zeile vor der laufenden Zeile).
Die absolute Adressierung
Die relative Adressierung (im Bezug auf die laufende Adresse)
Eine Zeile kann aber auch mithilfe eines Zeichenmusters (regular expression) identifiziert bzw. adressiert.
Eingabe Erläuterung Zeile1 Zeile Nummer Zeile1.
. Die laufende Zeile.
1 Erste Zeile im Dateipuffer.
$ Letzte Zeile im Dateipuffer.
0 Hypothetische Zeile vor der ersten Zeile im Dateipuffer. Sie wird beispielsweise verwendet, wenn ein Textabschnitt am Anfang der Dateipuffer (vor der ersten Zeile) verschoben werden soll.
+n bzw. -n Zeile, die n Zeilen nach (+n) oder vor (-n) der laufenden Zeile liegt. Abkürzung für (.+n) bzw. (.-n).
/Zeichenkette/ Erste Zeile nach der laufenden Zeile, die Muster Zeichenkette enthält (Vorwärtssuche).
?Zeichenkette? Erste Zeile vor der laufenden Zeile, die Muster Zeichenkette enthält (Rückwärtssuche).
Zeile1, Zeile2 Bereich zwischen Zeile Nummer Zeile1 und Zeile Nummer Zeile2 inklusive.
Zeile1,+n bzw.
Zeile1,-n (n positiv)Bereich zwischen Zeile Nummer Zeile1 und Zeile Nummer Zeile1+n bzw. Zeile Nummer Zeile1-n inklusive (n+1 Zeilen werden ausgewählt).
.,+n bzw.
.,-nBereich zwischen der laufenden Zeile und der Zeile, die n Zeilen danach (+n) oder davor (-n) liegt (Der Bereich enthält n+1 Zeilen). Abkürzung für den Bereich (.,.+n) bzw. (.,.-n).
, Der gesamte Dateipuffer. Abkürzung für (1,$).
; Der Rest des Dateipuffers ab der laufenden Zeile inklusive. Abkürzung für den Bereich (.,$).
Zeile1, /Zeichenkette/ Bereich zwischen Zeile Nummer Zeile1 und der (nach Zeile 1) nächsten Zeile, die Muster Zeichenkette enthält (Vorwärtssuche).
/Zeichenkette1/, /Zeichenkette2/ Bereich zwischen der ersten Zeile (nach der laufenden Zeile), die Muster Zeichenkette1 enthält und der darauffolgenden Zeile, die Muster Zeichenkette2 enthält. Achtung: Sollte die erst gefundene Zeile Zeichenkette1 und auch Zeichenkette2 enthalten, entspricht der adressierte Bereich nur dieser einen Zeile.
Zeile1, ?Zeichenkette? Bereich zwischen Zeile Nummer Zeile1 und der (vor Zeile 1) vorhergehenden Zeile, die Muster Zeichenkette enthält (Rückwärtssuche).
Anmerkung zur Tabelle Beispiele von Adressierungen
Es ist nicht sicher, ob alle Angaben von Bereichen in Rückwärts-Richtung (z.B. [Zeile1, Zeile2] mit Zeile2 kleiner-gleich Zeile 1) von ed unterstützt werden. Der ex-Editor - zumindest in manchen vim-Dialekten - unterstützt sie.
Die Eingabe einer einzelnen Zeile (ohne explizites Kommando) entspricht - wenn gültig - einer Bewegung der Cursorposition. Befindet sich die anvisierte Zeile jedoch nicht im Dateipuffer, hängt das Ergebnis vom Einzelfall ab.
- Wird eine Zeilennummer eingegeben, die größer als die Gesamtzahl der Zeilen im Dateipuffer ist, springt der Cursor auf die letzte Zeile des Textes.
- Wird ein unauffindbares Zeichenmuster eingegeben, tut der Editor nichts.
- Grundlegende Befehle:
Die nützlichsten Befehle oder Befehlsmuster werden unten aufgezeigt. Wird keine Adresse explizit eingegeben, betrifft die Befehlsliste die laufende Zeile des Dateipuffers (wo sich der Arbeitszeiger gerade befindet).
Eingabe Erläuterungen n Befehlsliste Führe die Befehlsliste für Textzeile Nummer n. Nach Ausführung sitzt der Zeiger auf Zeile n.
1,$ Befehlsliste Führe die Befehlsliste für jede Textzeile - von der ersten Zeile (1) bis zur letzten Zeile ($). Nach Ausführung sitzt der Zeiger auf der letzten Zeile.
/re/ Befehlsliste Führe die Befehlsliste für die erste Textzeile, welche dem Zeichenmuster re entspricht (vorwärts Suche). Nach Ausführung sitzt der Zeiger auf der Zeile, die die Befehlsliste betraf - oder bleibt unverändert, falls die Suche erfolglos blieb.
?re? Befehlsliste Führe die Befehlsliste für die erste Textzeile, welche dem Zeichenmuster re entspricht. (rückwärts Suche). Nach Ausführung sitzt der Zeiger auf der Zeile, die die Befehlerliste betraf - oder bleibt unverändert, falls die Suche erfolglos blieb.
(1,$) g/Zeichenmuster/ Befehlsliste Führe Befehlsliste für jede Textzeile im eingegebenen Adressenbereich aus, in der das Zeichenmuster Zeichenmuster auftritt. Implizit entspricht der Adressenbereich dem gesamten Dateipuffer. Nach Ausführung sitzt der Zeiger auf der zuletzt bearbeiteten Zeile der Zielmenge. Ist diese Menge leer - d.h. passt keine Zeile im Bereich dem Muster -, bewegt sich der Arbeitszeiger nicht.
(1,$) v/Zeichenmuster/ Befehlsliste Ist komplementär zu (1,$) g/Zeichenmuster/ Befehlsliste: Führe die Befehlsliste für alle Zeilen im eingegebenen Adressen-Bereich, die nicht das Zeichenmuster enthält. Impliziter Adressenbereich ist der gesamte Dateipuffer. Nach Ausführung befindet sich der Arbeitszeiger auf der zuletzt bearbeiteten Zeile - bleibt unverändert, wenn die Zielmenge der Adressen leer ist.
Es folgen einige Befehle im Befehlsmodus (nicht alphabetisch).
Befehl Bedeutung = Zeige die Anzahl aller Zeilen im Dateipuffer .= Zeige die Nummer der laufenden Zeilen im Dateipuffer
/Zeichenkette/= Zeige die Nummer der nächsten Zeile (nach der laufenden Zeile), die Muster Zeichenkette enthält. Es folgen einige Befehle im Befehlsmodus (alphabetisch).
Befehl Erläuterung co Befehl copy:
Synonym von Kommando t.(.,.) d Befehl delete:
Lösche die Zeilen im eingegebenen Bereich aus dem Dateipuffer. Implizit bezieht sich die Adressierung auf die laufende Zeile.(.,.+1) j Befehl join:
Füge alle Zeilen des eingegebenen Bereiches zusammen d.h. alle Zeilen werden nach Ausführung als eine einzige Zeile aufgefasst. Implizit bezieht sich die Adressierung auf die laufende Zeile und die Nachfolgerin.(.,.) m Zeilennr Befehl move:
verschiebe die Zeilen des eingegebenen Bereiches hinter die Zeile Nummer Zeilennr. Implizit bezieht sich die Adressierung auf die laufende Zeile.(.,.) n Befehl print with number:
Zeige den Inhalt der Zeilen aus dem eingegebenen Bereich mit der Adresse (Nummer) davor auf. Implizit bezieht sich die Adressierung auf die laufende Zeile.(.,.) p Befehl print:
Gleicht dem Befehl 'n', mit dem Unterschied, dass die Zeilennummer nicht angezeigt wird.q Befehl quit: Beende den Editor
Wenn Änderungen vorliegt, die nicht gesichert wurden, gibt ed eine Fehlermeldung aus und verweigert die Durchführung.
Wird der Befehl dann wiederholt, beendet ed die Sitzung (Nicht gesicherte Änderungen werden verloren).($) r Dateiname Befehl read file:
Lese Datei Dateiname und füge ihren Inhalt nach der adressierten Zeile ein. Implizite Adresse ist die letzte Zeile des Dateipuffers.($) r !Shellbefehl Befehl read output:
Führe den Shellbefehl 'Shellbefehl' aus und füge seine Ausgabe nach der adressierten Zeile ein.
Implizite Adresse ist die letzte Zeile des Dateipuffers.(.,.) s/ZMuster/EString/
(.,.) s/ZMuster/EString/g
(.,.) s/ZMuster/EString/n
(.,.) s/ZMuster/EString/c
Befehl search (and replace):
Für alle Zeilen im eingegebenen Adressierungsbereich suche das 'ZMuster' und ersetze es mit dem 'EString'. Implizite Adresse ist die laufende Zeile des Dateipuffers. Die nachgestellten Optionen:- Standardmäßig wird nur das erste Zeichenmuster der Zeile ersetzt.
- Wird Option g nachgestellt, werden alle (general) Zeichenmuster ersetzt.
- Wird Option n nachgestellt, werden nur die ersten n Zeichenmuster ersetzt.
- Wird Option c nachgestellt, fragt vi für jeden Treffer den User um Bestätigung (confirmation), ob ersetzt werden soll oder nicht.
(.,.) t (.) Befehl transfer (copy):
Kopiere die Zeile des eingegebenen Bereichs hinter die (nach dem Befehl) eingegebene Adresse. Implizite Adresse - für Quelle und Ziel des Transfers - ist die laufende Zeile des Dateipuffers (d.h Befehl 't' allein dupliziert die laufende Zeile).(1,$) w Dateiname Befehl (over)write:
Schreibe den Inhalt des Dateipuffers in Datei Dateiname. Wird kein Dateiname eingegeben, sind zwei Alternativen möglich:- Wurde am Anfang der Editiersitzung eine Datei geöffnet, überschreibt ed diese Quellendatei bzw. sichert die Änderungen.
- Wurde ed ohne Eingabe einer Dateiname aufgerufen, wirft er einen Fehler und verweigert die Ausführung, solange bis ein Dateiname eingetragen wird.
Impliziter Adressenbereich ist der gesamte Dateipuffer. Der Arbeitszeiger bewegt sich nicht.(1,$) wq Dateiname Befehl write and quit:
Führe beide Befehle 'schreibe Datei' und 'Beende ed' der Reihe nach.(1,$) W Dateiname Befehl write (append):
Gleicht dem Befehl 'w' mit dem Unterschied, dass der Pufferinhalt nicht den Inhalt der Zieldatei überschreibt, sondern angehängt wird.!Shellbefehl Befehl execute shell command:
Ein Befehl der aktiven Shell wird durchgeführt. Der Arbeitszeiger bewegt sich nicht.Es folgen Befehle um in den Eingabemodus zu gelangen (alphabetisch). Um den Eingabemodus wieder zu verlassen, müssen auf eine neue Zeile die Zeichen '.' und Rückgabe (Return) eingegeben werden.
Befehl Bedeutung (.) a Befehl append:
Hänge Text nach der adressierten Zeile an. Wurde keine Adresse eingegeben, gilt die laufende Zeile (='.')(.,.) c Befehl change:
Ersetze Text vom adressierten Bereich. Wurde kein Bereich eingegeben, gilt die laufende Zeile (='.,.')(.) i Befehl insert:
Füge Text vor der adressierten Zeile an. Wurde keine Adresse eingegeben, wurde gilt die laufende Zeile (='.')
Anmerkungen:Befehlsliste: Meistens wird nur ein Befehl eingetragen. Sollten aber mehrere Befehle eingetragen werden, muss jeder Befehl auf eine getrennte Zeile eingegeben werden - mit dem Backslach '\' als Fortsetzungszeichen am Ende aller Zeilen, bis auf die Letzte.
- Editiermodi:
-
ed kann auch im Skriptmodus (für die automatisierte Bearbeitung) aufgerufen werden.
- Mit Eingabe einer Skriptdatei:
Dabei entspricht jede Zeile der Skriptdatei einem Befehl, der der Reihe nach ausgeführt wird. Wenn die zu editierende Datei DateiName und die Skriptdatei SkriptDateiName heissen, sieht der Aufruf wie folgt aus:
> ed -s DateiName < SkriptDateiNameAnbei Beispiele von einfachen Skriptdateien
-
Inhalt der Skriptdatei in zwei Zeilen:
Ziel: Nach dem Aufruf wird in Datei DateiName jedes Zeichen 'ü' mit der Zeichenkette 'ue' ersetzt sein.
> g/ü/ s//ue/g
> wq -
Inhalt der Skriptdatei in zwei Zeilen:
Ziel: Nach dem Aufruf wird in Datei DateiName jede Zeile, wo Zeichenkette '100;' auftritt, aufgezeigt.
> g/100;/ p
> q!Das Unix-Tool
grep ist vom ed-Befehl in diesem Beispiel abgeleitet: g/re/ p (d.h. find all lines containing regular expression re and print them). Der Befehl wurde als eigenständiges Programm - mit eigenen Optionen - gesondert. D.h eine bessere Möglichkeit, das Ziel aus diesem Beispiel zu erreichen, ist folgender Eintrag auf der Kommandozeile:
> grep "100;" DateiNameAn dieser Stelle sei von einer verbreiteten Sitte abzuraten, nach der anstelle des direkten grep-Eintrages die Befehlskette cat + grep eingetippt wird:
> cat DateiName | grep "100;"Es funktioniert zwar auch, da der
cat-Befehl eine einzige Datei als Parameter zulässt. Es verschwendet aber unnötig Ressourcen: cat steht für concatenation: Es werden mehrere Dateien (die Befehlsargumente) gelesen und in einem zusammenhängenden Datenstrom auf stdout ausgegeben. Durch Umleitung bzw. piping kann die Ausgabe weiterverarbeitet werden. (Im Beispiel wird sie einem grep-Befehl zugeführt).
-
- Direkte Eingabe der Verarbeitungskette:
Anstatt eine Skriptdatei als Argument einzutragen, kann die Befehlskette direkt auf die Kommandozeile eingetippt werden. Dazu bedient man sich folgender Syntax:
>ed -s DateiName <<!
>g/100;/ p
>!Das Ziel gleicht demjenigen im vorherigen Beispiel: Datei DateiName lesen und nur die Zeilen herausgeben, die das Zeichenmuster 100; enthalten.
- Mit Eingabe einer Skriptdatei:
-
-
Eine Liste aller Befehle von ed ist beispielsweise
den
Open-BSD manpages (Englisch) zu entnehmen.
-
Auf der Seite 'Softwarepanorama'
wird eine
Beschreibung (Englisch), die auch zum Nachschlagen gut geeignet ist.
-
Eine Liste aller Befehle von ed ist beispielsweise
den
-
-
-
Merkmal: Zeilenorientierung versus Bildschirmorientierung
ed arbeitet zielenorientiert.
Nicht nur sind die einzelnen Zeilen des bearbeiteten Texts - d.h. die Zeichenketten zwischen 2 aufeinanderfolgenden LineFeed-Zeichen, LF (ASCII-Code=10) - die atomaren Blöcke, aus denen ed den Text zusammensetzt. ed zeigt gewöhnlich nur die laufende Zeile an. Der User kann zwar über einen Befehl Print Line (p) oder Line Number (n) eine lokale Abbildung des Dateipuffers anfordern z.B. Befehl "-3,+3 n" zeigt einen Textabschnitt von 7 Zeilen - 3 vor und 3 nach der laufenden Zeile. Er kann aber nicht ohne expliziten Befehl auf eine bestimmte Zeile springen.
Alle gängigen interaktiven Texteditors sind heutzutage bildschirmorientiert: Der User sieht auf dem (Terminal)-Bildschirm den Abschnitt des Textes, an dem er arbeitet und kann den Arbeitszeiger mit der Maus oder über Tasten bewegen. Unter diesen Umständen dürfte ein zeilenorientierter Texteditor, wie ed - oderedlin in Windows Betriebssystemen - als interaktiver Texteditor kaum vonnutzen sein.
-
Merkmal: Unterscheidung zwischen Editiermodi
Für den Ungeübten dürfte die Handhabung der Editiermodi, Befehlsmodus und Eingabemodus, schwierig zu verinnerlichen sein - insbesondere die Tatsache, dass der Editor nicht sofort und immer für die Eingabe bereit steht.
Verbreitete Texteditors - wie z.B. UltraEdit oder JEdit , die sowohl unter Windows, als auch unter Unix oder OSX verfügbar sind - arbeiten grundsätzlich im Eingabemodus: Der User kann ohne weitere Vorbereitung Text einfügen. Der Befehlsmodus wird implizit über Tastenkombination aufgerufen. Beispielsweise öffnet die Tastenkombination STRG+F (Befehl Find) ein Fenster auf, wo der User intuitiv Einstellungen einer Suchfunktion eintragen kann. Trotz des höheren Lernaufwands haben sich Texteditors, wie vi, wo der User Befehl- und Eingabe- Modus explizit steuert, behaupten können. Die Gründe sind:- Freie Verfügbarkeit: Auf unixoiden Systemen werden solche Editors - z.B. vi - standardmäßig und ohne zusätzliche Lizenzgebühren installiert.
- Flexibilität und Mächtigkeit der Funktionen: Mit Hilfe von Zeichenmustern kann z.B. der eingeübte User die Suchfunktion viel feiner gestalten, als in den Suchfenstern der meisten Texteditors möglich.
Anm.: Suchfenster, die eine ähnliche Flexibilität bieten, sind denkbar. Mit steigender Komplexität der Einstellungen verliert die Bedienung ihren intuitiven Charakter. Im gleichen Schritt wird vermutlich der Kaufpreis eines solchen "advanced editor" steigen.
-
-
Übersicht der ed-"Nachfolger"
Wichtige Merkmale von ed sind auf die "Nachfolge"-Editors übertragen worden:
- Explizite Steuerung der Editiermodi (wenn interaktiv bedient)
- Adressierungsschema und Syntax
- Befehle und Syntax
Editor Erläuterung / Merkmale ex
ex ist ein zeilenorientierter Texteditor, der als Erweiterung (Übermenge) von ed entwickelt wurde, als ed Unix-Standardeditor war. vi Aus Anwendersicht ist vi die visuelle (bildschirmorientierte) Betriebsart vom (zeilenorientierten) Texteditor ex. Aus diesem Grund lässt sich der Befehlsmodus auf zwei Weisen bedienen:
- Zum einen über vi-spezifische Tastenkombinationen, wie z.B.
- dd: delete, lösche laufende Zeile - und kopiere sie in den Standard-Zwischenpuffer
- yy: yank, kopiere laufende Zeile in den Standard-Zwischenpuffer
- ZZ: sichere den aktuellen Stand des Dateipuffers und schließe die Sitzung zu
Zum anderen über die ex-Befehle, die eine größere Flexibilität der Verarbeitung ermöglichen. ex-Befehle werden in die ex-Zeile eingetragen, welche im Befehlsmodus mit der Taste ':' aktiviert wird.
Im Gegensatz zu ed lässt sich vi nur interativ bedienen. Details zur Handhabung von vi bzw. ex sind u.a. folgenden Seiten zu entnehmen:sed
Wie auch ex leitet sed seine Syntax von ed ab. - sed steht für Stream EDitor und wird zur Verarbeitung von Text-Datenströmen herangezogen: Die Eingabedaten werden bearbeitet und weitergeleitet.
- Verglichen mit vi liegt sed auf der entgegengesetzten Richtung des ed-Weiterentwicklungsbaums: sed arbeitet nur im Stapelmodus. Jeder Befehl der Stapeldatei wird auf jede Zeile der zu editierenden Datei (Quelle des Datenstroms) - der Reihe nach - ausgeführt.
Daraus ergeben sich zwei wesentliche Unterschiede zu ed.- sed schreibt keine Ergebnisse auf irgendwelche Datei, es sei denn von einer Shell Umleitung veranlasst.
- Der implizite Bereich eines ed-Befehls ist die laufende Zeile. Der implizite Bereich eines sed-Befehl ist die gesamte Datei. Die Eingabe eines expliziten Zeilenbereiches erweitert (expand) in ed die Wirkung des Befehls, und beschränkt (narrow) sie in sed.
Weitere Information zu sed ist u.a. folgenden Quellen zu entnehmen: