Open Source im professionellen Einsatz

© A. Reinkober, Pixelio.de

Perl stattet beliebige Skripte mit kostenloser History aus

Wenigschreiber

Wer seinem interaktiven Perl-Tool einen ebenso schicken wie praktischen History-Mechanismus mit Editierfunktion spendieren möchte, der braucht nur die GNU-Readline- und History-Libraries einzubinden und jeweils eine ihrer Funktionen zu nutzen.

Die GNU-Utilities »readline« und »history« gehören zu den Dinosauriern der IT, gleichwohl erweisen sie sich nach wie vor als überaus nützlich: Mit ihnen kann jedes Kommandozeilen-Programm ohne viel Eigeninitiative einen Mechanismus zum Editieren und Wiederholen von User-Eingaben anbieten.

Längliches SQL

Wer zum Beispiel im MySQL-Client »mysql« (Abbildung 1) eine längliche SQL-Abfrage eintippt, der weiß es sicherlich zu schätzen, dass er sie durch einen Druck auf die [Cursor-up]-Taste beim nächsten Eingabeprompt wieder hervorholen kann. Entweder, um sie dann nochmals abzusetzen, oder auch, um sie zu modifizieren. Diese Funktionen sind übrigens unabhängig von dem Kommando »e«, mit dem der MySQL-Client eine weitere Möglichkeit der Eingabekorrektur bietet. Wenn sich beispielsweise beim Eingeben einer langen Zeile herausstellt, dass das erste Wort einen Fehler enthält, dann fährt der User einfach mit dem Cursor zurück zum Zeilenanfang und berichtigt den Fehler dort, bevor er schließlich das Kommando abschickt.

Abbildung 1: Eine Kommandozeilen-Session mit dem MySQL-Client »mysql«.

Abbildung 1: Eine Kommandozeilen-Session mit dem MySQL-Client »mysql«.

Wie ein Blick in den MySQL-Sourcecode verrät, implementiert die Datenbank den praktischen Mechanismus gar nicht selbst, sondern nutzt lediglich die C-Funktionen »readline()« und »add_history()« der GNU-Readline- und History-Libraries, um Benutzereingaben einzulesen und ausgewählte Kommandos zum später aufrufbaren History-Pool hinzuzufügen. GNU-typisch bringen die Befehle »info readline« und »info history« die vollständigen Manualseiten der Utilities im 70er-Jahre-Look ans Licht. Mit der [N]-Taste springt »info« zum nächsten Kapitel, mit [P] zurück zum zuletzt betrachteten und die [Tab]-Taste tastet sich innerhalb einer Seite zum nächsten verlinkten Aufzählungspunkt vor.

Sogar nach einem Neustart des MySQL-Clients ist die History-Information der letzten Session noch abrufbar. Das Geheimnis: Wie Abbildung 2 zeigt, legt der verwendete GNU-History-Mechanismus die Information in der Datei »~/.mysql_history« ab. Das letzte Kommando »quit« erscheint nicht in der History-Datei, da MySQL nur nutzbringende Kommandos speichert und bei »quit« noch vor dem Aufruf von »add_history()« merkt, dass es hier nichts Aufhebenswertes gibt, und die Bearbeitung abbricht.

Abbildung 2: In der Datei »~/.mysql_history« liegen die eingegebenen Kommandozeilen für später aufgerufene Sessions abrufbereit.

Abbildung 2: In der Datei »~/.mysql_history« liegen die eingegebenen Kommandozeilen für später aufgerufene Sessions abrufbereit.

Perl schottet ab

Perl bietet verwöhnten Skriptprogrammierern eine komfortable Schnittstelle zu den GNU-Libraries an. Das Perl-Modul Term::ReadLine::Gnu vom CPAN kommuniziert hierfür mit dem C-Layer der ebenfalls installierten GNU-Libraries und präsentiert sich dem Perl-Programmierer als objektorientierte Schicht. Das Modul Term::ReadLine liegt Perl-Distributionen von Anfang an bei, es bietet allerdings nur eingeschränkte Funktionen. Erst durch die Installation von Term::ReadLine::Gnu vom CPAN ist Term::ReadLine voll funktionsfähig.

Listing 1 erzeugt ein Objekt der Klasse Term::ReadLine und ruft dessen Methode »readline()« auf. Die wiederum fordert den User dann mit dem ihr überreichten String (»input>«) zur Eingabe eines Kommandos auf. Enthält das eingegebene Kommando verwertbare Zeichen, ist es sinnvoll, es mit »add_history()« in den Zeilenspeicher zu übernehmen, um es später mit den Cursortasten wieder hervorkramen zu können.

Listing 1:
»readline-test«

01 #!/usr/local/bin/perl -w
02 use strict;
03
04 use Term::ReadLine;
05 my $term = Term::ReadLine->new("myapp");
06
07 while (1) {
08   my $input = $term->readline("input>");
09   last unless defined $input;
10   print "Input was '$input'n";
11  
12   if($input =~ /S/) {
13     $term->addhistory($input);
14   }
15 }

Das Beispiellisting macht es sich einfach und akzeptiert alles außer Leerzeichen als verwertbar, natürlich sind aber auch raffiniertere Prüfungen vorstellbar. Weitere Informationen zur Terminal-Programmierung unter Perl finden sich in den Manualseiten der beiden CPAN-Module sowie - allerdings eher spärlich - in der Perl-Literatur, zum Beispiel in [2].

Diesen Artikel als PDF kaufen

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook