Open Source im professionellen Einsatz

Vim-Makros in Perl schreiben

Prüfungsfrage

Der Editor Vim (Vi improved) unterstützt auch Perl-Plugins, die den gerade editierten Text auf Tastendruck manipulieren. Dabei lassen sich mit dem mächtigen Perl komplexe Funktionen deutlich schneller entwickeln als mit Vims eingebauter Skriptsprache.

Wenn sich jemand bei Yahoo für eine Einsteigerposition im Perl-Bereich bewirbt und das Vergnügen hat, bei mir im Interview zu landen, kann es sein, dass ich die folgende Frage stelle: Wie versieht man in Perl ein Listing mit Zeilennummern, wie sie beispielsweise in einer Zeitschrift üblich sind?

Das ist eine recht simple Aufgabe und jeder Kandidat löst sie. Frage ich aber, was zu tun wäre, damit die Zeilennummern bündig sind, kommen manche Prüflinge ins Schleudern.

Im Stress

Hat das Listing nämlich neun Zeilen, sind alle Zeilennummern einstellig. Bei Listings zwischen zehn und 99 Zeilen Länge sind sie zweistellig, wobei die einstelligen Nummern von 1 bis 9 linksseitig mit Nullen aufzufüllen sind (01 bis 09). Längere Listings, die aus mehr als 100 und weniger als 1000 Zeilen bestehen, verlangen dreistellige Zeilennummern, der Programmierer muss sie ab 001 durchnummerieren.

Nun formatiert Perls eingebaute »printf«-Funktion zwar Ziffern mit führenden Nullen. Mit einem Formatstring »%03d« aufgerufen, macht sie aus dem Integer »3« den String »003«, »99« verwandelt sich in »099«, und »100« bleibt »100«. Wie aber pumpt »printf« den String auf eine variable Länge auf? Falls mir jemand ein »if-elsif«-Konstrukt vorschlägt, das eine limitierte Anzahl von Ziffernlängen abprüft, gehen die Alarmglocken los und die Falltür zum Haifischbecken öffnet sich automatisch.

Liegt die Breite der höchsten Zeilennummer in der Variablen »$numlen« vor, hilft ein dynamisch zusammengebauter Formatstring (»"%0" . $numlen . "d"«). Das so in einem String abzulegen funktioniert aber nicht auf Anhieb, denn in »"%0$numlend"« würde Perl erfolglos nach der Variablen »$numlend« suchen. Alte Perl-Hasen wissen aber, dass sich ein Skalar statt als »$numlen« auch als »${numlen}« schreiben lässt. Das löst das Problem: »"%0${numlen}d"«.

Mit der Programmiersprache C aufgewachsene Haudegen erinnern vielleicht auch noch, dass »printf()« variable Formatfelder mit dem Platzhalter ».*« und einem zusätzlichen Parameter erlaubt. Der Aufruf »printf("%0.*d", 3, 1)« erweitert die Zahl »1« mit zwei führenden Nullen auf die Gesamtbreite drei. Ersetzt der Programmierer »3« durch eine Variable, hat er eine weitere Möglichkeit, die Zeilennummer auf eine dynamisch vorgegebene Breite aufzufüllen.

Zurück zur Schulbank

Doch woher die Länge »$numlen« der letzten Zeilennummer »$num« nehmen? Perl verwandelt eine Zahl bekanntlich leicht in einen String, dessen Länge sich einfach durch die eingebaute Funktion »length()« ermitteln lässt. Das Ergebnis des Aufrufs »length($num)« liefert so den Wert für »$numlen«.

Es gibt jedoch noch eine weitere Möglichkeit. Im Dezimalsystem sind die Ziffern einer Zahl von rechts nach links mit 100, 101, 102 und so weiter gewichtet. Die Zahl 15 zerlegt sich so zu 5*100 +1*101. Die Zahl 100, die drei Ziffern lang ist, lässt sich als 1*102 schreiben. Die Zahl 1000, die vier Ziffern lang ist, entspricht 1*103. Aus wie vielen Ziffern besteht also eine Zahl N?

Wer in der Schule aufgepasst hat, erinnert sich, dass das Ergebnis von "10 hoch wie viel ist x?" der Zehner-Logarithmus von x ist. Perl hat zwar keinen Zehner-Logarithmus, aber die Funktion »log()«, die den Logarithmus einer Zahl zur Basis e (der Eulerzahl) bestimmt. Und wer über ein Elefantengedächtnis verfügt, weiß noch, dass sich der Logarithmus von N zur Basis x, also logx N, bestimmen lässt, indem man logy N durch logy y teilt.

Im vorliegenden Fall ermittelt sich der Zehnerlogarithmus von N in Perl also durch log(N):log(10). Die Ziffernlänge von N ergibt sich aus dem auf die nächste Ganzzahl abgerundeten und dann um 1 erhöhten Ergebnis der Logarithmusoperation.

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