- 1 - Der Bildschirmeditor vi Heller/ZfT Bearb.: Hoffmann/EED Mit Editor koennen ueber die Terminaltastatur Texte in Dateien eingetragen,geaendert und gelesen werden. Unter UNIX gibt es verschiedene Editoren. Waehrend in aelteren UNIX-Versionen ausschliesslich der Editor ed zur Verfuegung steht, enthalten heute fast alle UNIX-Systeme zusaetzlich den Editor vi. Mit vi wird waehrend der Bearbeitung einer Datei jeweils ein Dateiausschnitt am Bildschirm gezeigt. Diesen Ausschnitt bezeichnet man als Fenster. Auf der ganzen Bildschirmseite koennen Zeichen einfach durch Ueberschreiben geaendert oder neue Zeichen eingefuegt werden. Im Gegensatz zur dieser bildschirmorientierten Vorgehensweise arbeitet der Editor ed zeilenorientiert. Die Aenderung eines Zeichens in einer Zeile erfolgt entweder durch Neueingabe der ganzen Zeile oder durch ein Kommando zum Suchen und Ersetzen von Zeichenketten in der Zeile. Weil der Editor vi komfortabler als ed ist und daher auch bevorzugt benutzt wird, beschreiben wir hier den Editor vi. Es sei aber erwaehnt, dass es neben vi in einigen herstellerbezogenen UNIX- Versionen weitere Editoren mit sehr einfacher Bedienung gibt. Grundlagen vi aufrufen und beenden Das Kommando vi datei laedt die Datei vom Plattenspeicher in einen Teil des Hauptspeichers , dem Editor-Buffer, und zeigt die ersten 23 Zeilen von datei auf dem Bildschirm. Falls eine Datei mit Namen datei noch nicht existiert, wird sie von Editor selbstaendig angelegt. December 2, 1987 - 2 - Mit vi-Kommandos kann jetzt der Inhalt des Buffers bearbeitet - z.B. Text eingefuegt werden. der Inhalt von datei bleibt aber solange unveraendert, bis der bearbeitete Buffer mit :w gefolgt von RETURN, auf den Plattenspeicher zurueckgeschrieben (gerettet) wird. Beendet wird vi mit einem der folgenden (mit RETURN abzuschliessenden) Kommandos: :q beendet den editor. das Kommando wird nur akzep- tiert, wenn vorher der Bufferinhalt mit :w gerettet und seitdem bzw. seit dem Aufruf vom vi nicht mehr modi- fiziert wurde. xq entspricht dem Hintereinanderfuehren von :w und :q. Der Bufferinhalt ueberschreibt die alte Version von datei, vi wird beendet. :wq ist der uebliche Ausstieg aus vi. Je nach System wird auch das Kommando ZZ statt :wq benutzt. Die Mnemonic von ZZ soll an"schlafen" erinnern. :q! beendet den Editor, auch wenn der Bufferinhalt vorher nicht gerettet wurde. :q! wird benutzt, wenn mann die im Editor Modifikationen im Buffer nicht in datei uebernehmen moechte. Tritt waehrend der Arbeit mit vi ein System-Crash durch Hardware- oder Betriebssystemfehler auf, geht der Inhalt des Hauptspeichers und somit auch der Editor- Buffer verloren. auch wenn solche Ereignisse nur sel- ten vorkommen, empfielt es sich doch, bei laengeren Arbeiten mit vi gelegentlich den Bufferinhalt mit :w zu retten. Als zusaetzliche Sicherung fuehrt vi Protokoll ueber die vom Benutzer ausgefuehrten Editor- Operationen. Dieses Protokoll wird dierekt auf den Plattenspeicher geschrieben und ermoeglicht damit oft eine Wiederherstellung des beim Crash zerstoerten Buffer-Inhalts. Trat beim Editieren der Datei datei ein Systemzusammenbruch auf, kann, nachdem der Rechner wieder laeuft, mit dem Kommando vi -r datei der Editor veranlasst werden, den verlorengegangenen Bufferinhalt wieder herzustellen und dem Benutzer zur weiteren Bearbeitung am Bildschirm anzuzeigen. Kommando-Eingabe Mit dem Start von vi befindet sich der Editor in einem Modus, in dem er die Eingabe von Kommandos erwar- tet. D.h. der Editor ist diesem Modus nicht fuer die December 2, 1987 - 3 - Texteingabe in die zu bearbeitende Datei bereit. Die meisten vi-Kommandos bestehen nur aus ein oder zwei Zeichen und werden nicht mit der RETURN - Taste abgeschlossen. Das eingegegebene Kommando erscheint auch nicht auf dem Bildschirm, sondern man sieht nur die Wirkung des Kommandos, zum Beispiel * :Bildschirmfenster und Cursor positionieren * :Einfuegen von Text ermoeglichen * :Zeichen oder Zeilen entfernen Die Wirkung der Kommandos bezieht sich auf das aktuelle Zeichen bzw. die aktuelle Zeile. Das ist das Zeichen, auf das der Cursor positioniert ist bzw. die dazugehoerige Zeile. Als Beispiel betrachten wir das Kommando x zum Loeschen eines Zeichen: der Cursor wird auf dem Bildschirm mit den Positionierungstasten auf das zu loeschende Zeichen positioniert. Durch Eintippen von x wird das Zeichen geloescht. Vielen Kommandos kann eine Zahl vorangestellt wer- den. So loescht z.B. 3x drei Zeichen ab Cursorposition. Nicht alle Kommandos sind so einfach wie x . Bei einigen Kommandos springt der Cursor auf die letzte Bildschirmzeile, die Kommandozeile , und zeigt dort die Eingabe an. In diesen Faellen ist das Kommando mit RETURN abzuschliessen. Das gilt zum Beispiel fuer alle Kommandos, die mit einem : beginnen. Einige davon haben wir bereits kennengelernt. (:w, :wq, :q!) Fenster und Cursor positionieren Durch Positionierung des Cursors zur unteren oder oberen Bildschirmzeile wird der Bildschirminhalt bewegt, d.h. das Fenster verschiebt sich jeweils um eine Zeile nach unten bzw. oben. Zusaetzlich laesst sich das Fenster mit folgenden Kommandos seitenweise(1 Seite = 23 Zeilen) verschieben: ^F blaettert eine ganze Seite vorwaerts ^B blaettert eine ganze Seite rueckwaerts ^D blaettert eine halbe Seite vorwaerts ^U blaettert eine halbe Seite rueckwaerts nG zeigt die Seite, in der die n-te Zeile der datei steht G zeigt letzte Seite der Datei. Zur Positionierung des Cursors exsitieren neben den bereits erwaehnten Positionierungstasten die folgenden December 2, 1987 - 4 - Kommandos: - Anfang der vorhergehenden Zeile ^ Anfang der aktuellen Zeile $ Ende der aktuellen Zeile + Anfang der naechsten Zeile RETURN gleiche Wirkung wie"+" w Anfang des naechsten Wortes b Anfang des letzten Wortes e Ende des aktuellen Wortes Texteingabe und - aenderung Text einfuegen Durch die im folgenden aufgefuehrten Kommandos geht vi in den Ein- modus: der nach dem Kommando eingegebene Text wird in die beim Aufruf vom vi angege- bene Datei geschrieben. Zeilen werden durch das Druecken der RETURN-Taste abgeschlossen. Verlassen wird der Eingabe modus durch das Druecken der Taste ESC, nach ESC eingegebene Zeichen werden vom vi wieder als Kommandos interpretiert. i ... ESC Einfuegen vor der Cursorposition I ... ESC Einfuegen am Anfang der aktuellen Zeile a ... ESC Einfuegen nach der Cursorposition A ... ESC Einfuegen am Ende der aktuellen Zeile o ... ESC neue Zeile hinter der aktuellen Zeile einfuegen O ... ESC neue Zeile vor der aktuellen Zeile ein- fuegen Aenderung und Loeschen Zum Aenderung und Loeschen von text stehen mehrere Kommandos zur Verfuegung. Die folgende Auswahl hat sich in der Praxis als nuetzlich herausgestellt. rx Ersetze aktuelle Zeichen durch das Zeichen x cw ...ESC Uberschreibe Rest des aktuellen Wortes, Einfuegemodus beenden mit ESC C ... ESC Ueberschreibe Rest der aktuellen Zeile x Loesche aktuelles Zeichen dw Loesche Rest des aktuellen Wortes D Loesche Rest der aktuellen Zeile dd Loesche aktuelle Zeile J Ersetze NEWLINE in aktueller Zeile durch ein Leerzeichen, d.h. verknuepfe aktuelle und folgende Zeile zu einer Zeile December 2, 1987 - 5 - Verschieben und Kopieren von Text Der jeweils zuletzt geloeschte Text wird vom vi in einem paste buffer aufgehoben. Mit dem Kommando p wird der Bufferinhalt hinter der Cursorposition eingefuegt, mit P vor der Cursorposition. Damit steht ein einfacher Mechanismus zum Ver- schieben von Textstuecken zur Verfuegung: Der Text wird an einer Stelle geloescht und an einer anderen Stelle mit p wieder eingefuegt. Wir betrachten drei Beispiele: 4dd Loescht vier Zeilen ab der aktuellen Zeile (einschliesslich der aktuellen Zeile) p fuege geloeschte Zeile ein x Vertausche die beiden Zeichen ab der p Cursorposition dd Vertausche aktuelle und nachfolgende Zeile p Das p-Kommando veraendert nicht den Inhalt des paste-buffers, sein Inhalt kann damit mehrfach in die bearbeitete Datei uebernommen werden. Setzt man daher im ersten Beispiel zusaetzlich hinter 4dd das Kommando P, hat die Kommandofolge den Effekt:Kopiere 4 Zeilen ab der alten Cursorposition hinter die neue Cursorposi- tion. Der paste buffer kann auch gefuellt werden, ohne Text zu loeschen. Das Kommando nY schreibt n Zeilen ab der aktuellen Cursorposition in den paste buffer, der alte Bufferinhalt geht dabei ver- loren. Damit kann das Kopieren von Zeilen einfacher als oben beschrieben durchgefuehrt werden: 4Y Merke vier Zeilen ab der aktuellen Zeile Posi- tioniere auf die Zeile hinter der die vier Zeilen kopi- ert werden sollen. p Schreibe vier Zeilen. Beim Verschieben oder Kopieren groesserer Textstuecke ist es sicherer, mit Zeilennummer zu arbeiten. Das Kommando : set number bzw. : set nonumber schaltet die Zeilennummerierung ein bzw. aus. Die December 2, 1987 - 6 - Zeilennummern erscheinen nur auf dem Bildschirm und werden nicht in die Datei uebernommen. Die Nummer einer Zeile laesst sich auch mit :.= bestimmen. Das Kommando zeigt die Nummer der aktuellen Zeile, d.h. der Zeile, in der der Cursor steht. Anhand der Zeilennummern koennen dann mit : von,bis m nach die Zeilen von Nummer von bis Nummer bis hinter die Zeile mit der Nummer nach verschoben werden. Das Kopi- eren von Zeilen geht analog mit :von,bis c nach Suchen und Ersetzen Einfaches Suchen Nach Eingabe von /pattern RETURN durchsucht vi ab der aktuellen Zeile vorwaerts die zu bearbeitende Datei nach der Zeichenfolge pattern. Der Cursor wird auf das erste gefundene Auftreten der Zeichenkette pattern positioniert. Mit /RETURN oder mit dem Kommando n wird anschliessend jeweils das naechste Auftreten von pattern gefunden. Die Datei kann auch rueckwaerts durchsucht werden: Statt/ ist ? anzugeben. Die Zeichenkette pattern kann Sonderzeichen enthalten und beschreibt damit aehnlich wie ein regu- laerer Ausdruck eine Menge von Zeichenketten. Eine solche Zeichenkette bezeichnen wir als Muster: x.y xy, d.h. alle Zeichenketten, die mit x anfangen mit y aufhoeren und dazwischen genau ein Zeichen enthalten. x*y XnY n>0. Der Stern steht fuer beliebige Wiederho- lung des letzten Zeichens, er hat die Bedeutung des Kleene-Symbols. x.*y xy. Die Bedeutung von .* folgt aus der Bedeutung der Sonderzeichen . und *. x[ss]y ss sei eine Zeichenfolge a,b,c.... a[ss]y steht fuer alle Zeichenfolgen, die mit x anfangen, mit y enden und dazwischen genau ein Zeichen a aus ss enthalten. Fuer ss sind abkuerzende Schreibweisen moe- glich, z.,B. "a-z","A-Z","0-9". ^xyz Das Zeichen ^ bedeutet Zeilenanfang. ^xyz steht December 2, 1987 - 7 - fuer alle Zei chenketten xyz, die am Anfang einer Zeile stehen. xyz$ Das Zeichen $ bedeutet Zeilenende. xyz$ steht fuer alle Zeichen ketten xyz, die am Zeilenende stehen. /* Der Backslash"/" hebt die Wirkung eines nachfol- genden Sonder- zeichen auf."/*" steht somit fuer Zeichenkette"*". Freies Suchen und Ersetzen Die Funktion " Suche eine Zeichenkette ALT und ersetze sie durch eine Zeichenkette NEU" wird mit dem Kommando s ausgefuehrt. Der Kommandoaufruf hat im vi die allgemeine Form :adr s/ALT/NEU/g adr adr spezifiziert den Bereich der Datei, in dem die Substitution durchgefuehrt werden soll. falls adr weg- gelassen wird, bezieht sich das Kommando nur auf die aktuelle Zeile, d.h. auf die Zeile, in der vor der Eingabe von ":" der Cursor stand. Beispiele fuer adr sind: 24 Zeile 24 7,10 Zeile 7 bis einschliesslich Zeile 10 1,$ erste bis letzte Zeile($= letzte Zeile) % ganze Datei, aequivalent zu 1,$ ALT ALT steht fuer die zu ersetzende Zeichenkette. ALT ist ein Muster, d.h. es kann die oben spezifizierten Son- derzeichen ent- halten und beschreibt dann eine Menge von Zeichenketten. NEU die Zeichenkette ALT bzw. alle die durch das Muster ALT beschriebenden Zeichenketten werden im mit adr spezifizierten Bereich durch die Zeichenkette NEU erstzt. /g g bedeutet general und bewirkt, dass in einer Zeile jedes Auftreten von ALT durch NEU ersetzt wird. Wird /g weggelassen, wird nur das erste Auftreten von ALT in einer Zeile durch NEU ersetzt. Die Anzahl der Zeilen in denen Ersetzungen durchgefuehrt werden, ist unabhaenig von g und wird allein durch adr bestimmt. Die folgenden Beispiele zeigen einige uebliche Anwendungen fuer das Suchen und Ersetzen von Zeichenk- etten: December 2, 1987 - 8 - :s/alt/neu In aktueller Zeile erstes Auftreten von alt durch neu ersetzen. :%s/alt/neu/ In der ganzen Datei jeweils ersts Auf- treten von alt in einer Zeile durch neu ersetzen. :%s/alt/neu/g In der ganzen Datei jedes Auftreten von alt durch neu ersetzen. :%s/alt/g In der ganzen Datei den String alt loeschen. :%s/(.*)//g In der ganzen Datei alle in Klammern stehenden Zeichenketten einschliesslich der Klammern loeschen. :%s/^/ / Alle Zeichen um zwei Blanks einruecken. :u undo-Kommando: hebt den Effekt des letzten substitute- Kommando auf. Sukzessives Suchen und Ersetzen Die "unbekuemmerte" Anwendung der oben beschriebenen Suchfunktionen kann zu nicht erwuenschten ergebnissen fuehren. Will man z.B. in einem PASCAL- Programm den Variablennamen "out" durch "aus" ersetzen , so wuerde das Kommando :%s/out/aus/g dies sicher leisten. Leider haette diese Anwendung auch zur Folge, dass in der Kopfzeile des Programmes der Dateiname output als Bezeichnung fuer das Standardaus- gabemedium in ausput verwandelt wuerde, was sicherlich nicht im Sinne des Programmierers ist. Haeufig benoetigt man daher eine Funktion:"suche eine Zeichenkette (bzw. ein Muster) ALT und ersetze sie jeweils nach Rueckfrage durch eine Zeichenkette NEU". wir beschreiben im Folgenden einen Weg, diese Funktion im vi auszufuehren. 1.) :%s/ALT/NEU/c eingeben und mit der RETURN-Taste abschicken. Es wird die erste Zeile, in der ALT gefun- den wurde, zusammen mit einem Pfeil ^^ auf ALT, unten am Bildschirm ausgegeben. 2.) Bei der Eingabe von y und RETURN wird ALT durch NEU ersetzt. Bei der Eingabe von RETURN allein wird nicht substituiert. Der Cursor zeigt anschliessend auf das naechste Auftreten von ALT. 3.) Der Modus wird durch ^C und RETURN vorzeitig abge- brochen. December 2, 1987 - 9 - Verschiedenes Dateien einfuegen und ausgeben Mit dem Aufruf :r file wird der Inhalt der angegebenen Datei file in den Edi- torbuffer eingefuegt (read). Die Einfuegung erfolgt ab der Zeile, in der vor Aufruf des Kommandos der Cursor stand. Entsprechend zu read kann mit dem bereits am Anfang erwaehnten write-Kommando der Buffer-Inhalt ganz oder teilweise in die Datei geschrieben werden. Die allgemeine Form des write-Kommandos ist : adr w file Der mit adr spezifische Bereich wird in die angegebene Datei geschrieben. Fuer adr sind die gleichen Angaben wie beim oben beschriebenen substitute-Kommando moe- glich. Wird adr weggelassen, bezieht sich das Kommando auf die ganze Datei. Ohne Angabe von file wird in die Datei geschrieben, aus der beim vi-Aufruf der Buffer geladen wurde. Bei der Angabe einer bereits vorhandenen Datei als file meldet vi einen Fehler. Um file zu ueberschreiben, muss : adr w! file eingegeben werden. Ausfuehren von Shell-Kommandos Vom Editor vi aus koennen SHELL-Kommandos aus- gefuehrt werden. Die folgenden drei Eingabemoegli- chkeiten werden am haeufigsten benutzt: : ! cmd Der Editor vi wird unterbrochen und das angegebene Shell-Kommando cmd wird ausgefuehrt. Nach Ausfuehrung des Kommandos befindet man sich wieder wie vor der Unterbrechung im vi. !Gcmd Das Shell-Kommando cmd wird ausgefuehrt. Das Kommando liest seine eingabe(stdin) aus dem Editor- buffer von der aktuellen Zeile bis zum Dateiende. Die Ausgabe des Kommandos(stdout) ersetzt den Inhalt des Editorbuffers ab der aktuellen Zeile. Nach Ausfuehrung des Kommandos befindet man sich wieder im vi. !! cmd Auch hier wird das Shell-Kommando ausgefuehrt und der Editorbuffer wie oben als Ein- und Ausgabe benutzt. Eingabe(stdin) ist hier aber nur die aktuelle December 2, 1987 - 10 - Zeile. Mit einer vorangestellten Zahl, z.B. 3!!cmd, kann die Anzahl der Eingabezeilen angegeben werden. In der ersten Form zeigt zum Beispiel :!pwd den Namen des Working-Directories an, dass davon die gerade editierte Datei betroffen ist. Dagegen ersetzt !!pwd die aktuelle Zeile durch den Namen des Working- Directories. der Inhalt der Zeile ist ohne Bedeutung, da pwd keine Daten von stdin liest. Als Eingabe wird die aktuelle Zeile beim Kommando !! sh benoetigt. sh ist der Kommandointerpreter Shell. Er liest die Zeile, fuehrt sie als Shell-kommando aus und ersetzt die Zeile durch die Kommandoausgabe. Als letztes Beispiel benutzen wir das Shell- Kommando sort. sort liest von stdin, sortiert die gelesenen Zeilen lexikografisch und schreibt sie nach stdout. Folglich werden mit !G sort alle Zeilen im Editorbuffer ab der aktuellen Zeile sor- tiert. Makros Mit einem Makromechanismus koennen im vi neue Kom- mandos definiert werden. Dazu dient das :map-Kommando. Nach Eingabe von map c string hat das Eintippen von K im Kommandomodus die Bedeutung von String. So bewirkt zum Beispiel die definition des Buchstabens K mit :map K 5ddG dass beim Eintippen von K im Kommandomodus 5 Zeilen Geloescht werden (5dd) und anschliessend der Cursor ans Dateiende positioniert wird(G). Um die RETURN- und ESC-Taste CX ESCAPE Taste in string benutzen zu koennen, wird ihnen ^V(controll V) vorangestellt. Ein Beispiel dafuer ist :map K oErste Zeile^V RETURN Zweite Zeile^V ESC Beim Druecken der Taste K im Kommandomodus werden zwei neue Zeilen eingefuegt. Das erste Zeichen in string, o, December 2, 1987 - 11 - erzeugt eine Leerzeile und wechselt in den Einga- bemodus. Rueckgaengig gemacht wird diese Makrosdefinition mit dem Kommando unmap K Grundsaetzlich koennen alle Zeichen zur Definition von Makros benutzt werden. Die folgenden Zeichen haben im vi keine Bedeutung und sind daher Kandidaten fuer mit map definierte neue Kommandos: K V v g q , ; _ * = Optionen einstellen Das Verhalten des Editor vi kann durch das Ein- stellen von Optionen beeinflusst werden. Die aktuelle Einstellung sieht man mit ignorecase Beim Suchen von Zeichenketten wird Gross- und Kleinschreibung ignoriert. list Das Tabulatorzeichen wird als ^I gezeigt und das Zeilenende mit $ markiert. number Die Zeilen werden mit einer vorangestellten Zeilennummer gezeigt. Eingestellt werden die Optionen durch Angabe des Optionsname im set-Kommando. So schaltet :set number die Zeilennummerierung ein. Aufgehoben wird eine Option mit einem vorangestellten "no" vor dem Optionsnamen, z.B. schaltet :set nomuber die Zeilennummerierung wieder aus. December 2, 1987