Perl

Aus Mikiwiki
Wechseln zu: Navigation, Suche

Die Programmiersprache Perl wurde 1987 von Larry Wall als Syntehse aus C, awk den Unix-Shell-Befehlen und anderen Einflüssen entworfen und war ursprünglich als Werkzeug zur Verarbeitung von Textdateien bei System- und Netzwerkverwaltung vorgesehen (etwa zur Auswertung von Logdateien). Hauptziele sind eine schnelle Problemlösung und grösstmögliche Freiheit für Entwickler. Die Bearbeitung von Texten mit Hilfe regulärer Ausdrücke sowie viele frei verfügbare Module, die an einem zentralen Ort (CPAN) gesammelt werden, sind Stärken der Sprache.

Verwendung

Ersetzen von Textstellen in mehreren Dateien gleichzeitig. Sonderzeichen ( / . ^ $ usw.) können gefluchtet werden.

$ perl -pi -w -e 's/search/replace/g;'

Kurs vom 28.-31. Januar 2008

Zusammenhängen zweier Zeichenketten.

$string = $string1 . $string2;

Anhängen an eine bestehende Zeichenkette.

$string = $string . $anhang;
$string .= $anhang;

print mit zwei Argumenten.

print $ergebnis, "\n";

print mit Umwandlung in eine Zeichenkette und Anhängen des Zeilenendes.

print $ergebnis . "\n";

print ...

print "$ergebnis \n";

Einlesen einer Zeile aus der Standardeingabe.

while ($line = <STDIN>) {
  print $line;
}

Einlesen der Standardeingabe in ein Array.

@lines = <STDIN>;

$ cat /etc/hosts
$ perl skriptname < /etc/hosts

Einige Konzepte.

$ Skalar
@ Array. Einzelnes Element: $ []
% Hash. Einzelnes Element: $ {}
  • Implizite Umwandlung von Zahlen und Zeichenketten
  • Skalarer Kontext und Listenkontext

Listen-Arrays

(Ergänzung zu Übung 4-4)

perldoc perldata
| list value constructor |
http://faq.perl.org
perlfaq4 Data manipulation
Data: Arrays

Arrays und Listen

Arrays können manipuliert werden, Listen stehen einfach so "da".

Zuweisung des Werts der Variable "$bar" an die Skalarvariable "$foo".

$foo = ('cc', '-E', $bar);

Die Variable "$foo" erhält den Wert "3".

@foo = ('cc', '-E', $bar);
$foo = @foo;

Hashes

%hash = ('a', 'key1', 'b', 'key2');

%hash = ('key1' => 'a',
         'key2' => 'b',
        );

Weitere Zuweisung an das Hash "%hash".

%hash{key3} = "c";

Mustererkennung mit regulären Ausdrücken

Jede Zeile, in der kein "$"-Zeichen vorkommt. Der Schalter "-n" impliziert, dass eine Schlaufe der Art while (<>) { ... } print um das Konstrukt herum entsteht. Der Schalter "-e" steht für das dahinter folgende Skript.

$ perl -ne 'print if /'^[^\]$/'
$ perl -ne 'print if /^fred|fred$/'
$ perl -ne 'print if m(^fred|fred$)'
$ perl -ne 'print if m(^fred|fred$)i'
$ perl -ne 'print if m/(...)$1/'
$ perl -ne 'print if m/(.)(.)(.)$1$2$3/'

Drei Zeichen gefolgt von denselben drei Zeichen in umgekehrter Reihenfolge.

$ perl -ne 'print if m/(.)(.)(.)$3$2$1/'
$ perl -wne 'print if m[(.)(.)(.)\3\2\1]g'
$ perl -wne '@a = split /s\s+/; print $#a+1, "\n"'
abc
1
abc abc abc
3
$ perl -wne '@a = split /s\s*/; print $#a+1, "\n"'
abc abc abc
9

Zählen aller Worte, in denen alle Vokale vorkommen.

perl -ne 'print if /a/i and /e/i and /i/i and /o/i and /u/i' < /usr/share/dict/words | head -5

$line = <>;
if ($line =~ /a/i and
    $line =~ /a/i and
    $line =~ /a/i and
    $line =~ /a/i and
    $line =~ /a/i)

Wieviele Worte der Datei "words" enthalten doppelte Buchstaben (z. B. Billette).

perl -ne 'print if /(.)\1.*(.)\2/' < /usr/share/dict/words | wc -l
perl -ne '$c++ if /(.)\1.*(.)\2/; END{print "$c\n"}' < /usr/share/dict/words
perl -ne '/(.)\1.*(.)\2/ && $c++; END{print "$c\n"}' < /usr/share/dict/words

Funktionen

Funktion, die als Argumente eine Zahl (1 bis 12) erhält und den entsprechenden Monatsnamen zurückliefert.

...

I/O-Operationen

open PS, "ps -ef |" or die "Cannot call ps $!";
while (<PS>) {
  print;
}

Filehandle "XXX"

open XXX, "ps -ef |" or die "Cannot call ps $!";
while (<XXX>) {
  unless (/^\s*kurs/) {print}
}

Beispiele

#!/usr/bin/perl

# In der Arrayvariablen "@zeilen" wird die Ausgabe des externen Befehls
# "perldoc -u -f atan2" gespeichert (dieser Befehl dient der Anzeige der
# Dokumentation von Perl, hier über die trigonometrische Funktion "atan2"). 
@zeilen = `perldoc -u -f atan2`;

# Die Schleifenfunktion "foreach" arbeitet jede der Zeilen in der
# Arrayvariablen "@zeilen" ab.
foreach (@zeilen) {
  
  # Veränderung jeder Zeile, die eine besondere Markierung (spitze Klammern)
  # enthält
  s/\w<([^>]+)>/\U$1/g;

  # Ausgabe jeder (möglicherweise veränderten) Zeile
  print;
} 

# Ausgabe des Befehls "perldoc -u -f atan2" auf der Shell wäre:
#
#
# =over 8
# 
# =item atan2 Y,X
# X<atan2> X<arctangent> X<tan> X<tangent>
# 
# Returns the arctangent of Y/X in the range -PI to PI.
# 
# For the tangent operation, you may use the C<Math::Trig::tan>
# function, or use the familiar relation:
# 
#     sub tan { sin($_[0]) / cos($_[0])  }
# 
# Note that atan2(0, 0) is not well-defined.
# 
# =back
#!/usr/bin/perl -w

# Einlesen eines Namens
$name = <STDIN>;

# Vergleich der eingelesenen Zeichenkette mit der Zeichenkette "fred", 
# wobei geprüft wird, ob erstere "grösser" als letztere ist. Dabei ist
# zu beachten, dass nach dem ASCII-Standard Grossbuchstaben Vorrang vor
# Kleinbuchstaben haben. Mit "chomp" wird das bei der Eingabe 
# miteingegebene Returnzeichen entfernt.
if (chomp($name) gt 'fred') {
  print "'\$name' folgt nach der Sortierung auf 'fred'.\n";
} else {
  print "'\$name' folgt nicht auf 'fred'.\n";
  print "Vielleicht handelt es sich um dieselbe Zeichenkette.\n";
}

Lesen aus der Standardeiungabe.

#!/usr/bin/perl -w

# Anstelle von <STDIN> liest Perl die nächste Zeile aus der Standardeingabe.
# Der Wert endet typischerweise mit dem newline-Zeichen. Zum Entfernen
# dieses Zeichens kann "chomp" vernwendet werden.
$zeile = <STDIN>;

if ($zeile eq "\n") {
  print "Nur eine leere Zeile...\n";
} else {
  print "Die eingegebene Zeile lautet: $zeile";
}

Operator "chomp".

#!/usr/bin/perl -w

chomp ($zeile = <STDIN>);

# Dasselbe bewirkt:
# $zeile = <STDIN>; chomp($zeile);

if ($zeile eq "\n") {
  print "Nur eine leere Zeile...\n";
} else {
  print "Die eingegebene Zeile lautet: $zeile";
}

Da "chomp" eine Funktion ist, hat es auch einen Rückgabewert, nämlich die Anzahl der entfernten Zeichen. Im folgenden Beispiel hat "$betty" also den Wert "1", da ein newline-Zeichen entfernt wurde.

$essen = <STDIN>;
$betty = comp $essen;

Die while-Schleife wiederholt einen Anweisungsblock, solange eine Bedingung wahr ist. Das folgende Beispiel gibt die Werte 2, 4, 6, 8 und 10 aus.

$zaehler = 0;
while ($zaehler <= 8) {
  $zaehler += 2;
  print "Der Zähler steht jetzt auf $zaehler\n";
}

$n = 1;
while ($n < 10) {
  # $summe hat zu Beginn der Schleife den Wert "undef" (verhält sich   # automatisch wie "0"). Beim ersten Schleifendurchlauf hat $n den Wert "1",
  # der automatisch zu "$summe" hinzugefügt wird, sodass "$summe" danach den
  # Wert "1" hat.
  $summe += $n;

  # Sprung zur nächsten ungeraden Zahl
  $n += 2;
}
print "Das Ergebnis ist $summe.\n";

Datenbankverbindung herstellen

Starten der Datenbank:
# /etc/init.d/mysqld start

$ mysqladmin -u root password mysql
$ mysql -u root -p
Password: mysql
mysql> GRANT ALL PRIVILEGES ON *.* TO 'testuser'@'localhost'
    -> IDENTIFIED BY 'geheim' WITH GRANT OPTION;
    -> quit
$ mysql -u testuser -p geheim

Skript zum Verbinden mit Datenbank.

#!/usr/bin/perl -w

use strict;
use DBI;

my $database = "test";
my $hostname = "localhost";
my $dsn      = "DBI:mysql:database=$database;host=$hostname";

my $user     = "testuser";
my $password = "geheim";

# Konstruktor und Verbindung
my $dbh      = DBI::->connect( $dsn, $user, $password,
                             { 'RaiseError' => 1,
                               'AutoCommit' => 1,
                             }) or die DBI::errstr;

# etwas mit der Datenbank tun...

# Verbindung wieder trennen
$dbh->disconnect;

Anlegen einer Tabelle auf der MySQL-Befehlszeile.

[kurs11@kr08-11 PERL]$ mysql -u testuser -p test
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.0.45 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test;
Database changed
mysql> CREATE TABLE vortrag (
    -> vortrag_id INTEGER,
    -> titel VARCHAR(127),
    -> sprecher_id INTEGER,
    -> minuten INTEGER);
Query OK, 0 rows affected (0.00 sec)

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| vortrag        | 
+----------------+
1 row in set (0.00 sec)

Anlegen einer Tabelle mit obigem Skript.

#!/usr/bin/perl -w

use strict;
use DBI;

my $database = "test";
my $hostname = "localhost";
my $dsn      = "DBI:mysql:database=$database;host=$hostname";

my $user     = "testuser";
my $password = "geheim";

# Konstruktor und Verbindung
my $dbh      = DBI::->connect( $dsn, $user, $password,
                             { 'RaiseError' => 1,
                               'AutoCommit' => 1,
                             }) or die DBI::errstr;

# etwas mit der Datenbank tun...
my $sql_create = qq/ CREATE TABLE vortrag_1 (
                     vortrag_id INTEGER,
                     titel VARCHAR(127),
                     sprecher_id INTEGER,
                     minuten INTEGER)          /;

my $resultcode_create = $dbh->do($sql_create);


# Verbindung wieder trennen
$dbh->disconnect;

Tabelle löschen mit obigem Verbindungsskript.

#!/usr/bin/perl -w

use strict;
use DBI;

my $database = "test";
my $hostname = "localhost";
my $dsn      = "DBI:mysql:database=$database;host=$hostname";

my $user     = "testuser";
my $password = "geheim";

# Konstruktor und Verbindung
my $dbh      = DBI::->connect( $dsn, $user, $password,
                             { 'RaiseError' => 1,
                               'AutoCommit' => 1,
                             }) or die DBI::errstr;

# etwas mit der Datenbank tun...
my $sql_drop        = qq/ DROP TABLE vortrag_1 /;
my $resultcode_drop = $dbh->do($sql_drop);


# Verbindung wieder trennen
$dbh->disconnect;

Daten in Tabelle einfügen.

#!/usr/bin/perl -w

use strict;
use DBI;

my $database = "test";
my $hostname = "localhost";
my $dsn      = "DBI:mysql:database=$database;host=$hostname";

my $user     = "testuser";
my $password = "geheim";

# Konstruktor und Verbindung
my $dbh      = DBI::->connect( $dsn, $user, $password,
                             { 'RaiseError' => 1,
                               'AutoCommit' => 1,
                             }) or die DBI::errstr;

# etwas mit der Datenbank tun...
my $vortrag_id = 142;
my $titel      = "Web Application Development mit mod_perl und CPAN";

my $sql_dynamisch = qq/ INSERT INTO vortrag (vortrag_id, titel) VALUES (?, ?)/;

my $sth    = $dbh->prepare($sql_dynamisch);
my $anzahl = $sth->execute($vortrag_id, $dbh->quote($titel)) 
  or warn $dbh->errstr;


print "Betroffene Datensätze: ", $anzahl + 0, "\n" if $anzahl;


# Verbindung wieder trennen
$dbh->disconnect;

Weblinks

Spreadsheets - Excel

Herausgeber Sprache Webseitentitel Anmerkungen