Schrift
[thread]6775[/thread]

Probleme mit anonymen subs

Leser: 2


<< |< 1 2 >| >> 14 Einträge, 2 Seiten
Ronnie
 2005-03-10 09:25
#52490 #52490
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
Auf der DaLUG-Mailingsliste hat jemand nach einer Möglichkeit gesucht in einer Logdatei Ersetzungen anhand einer Zuordnungsliste in einer weiteren Datei durchzuführen. Eine mögliche Lösung ist es eine LookUpTable zu bauen und dann Zeile für Zeile die Ersetzungen durch zuführen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/perl

use strict;
use warnings;

my %lookup;

for (<DATA>) {
chomp;
my ($k, $v) = split(/ -- /);
$lookup{$k} = $v;
}

while(<>) {
s/^(\w+)\b/$lookup{$1} || $1/e;
print;
}

_ _DATA_ _
uidf2920 -- Schulz
uid60124 -- Maier
uidg1626 -- Muster
uidg1067 -- Mueller

Dies war mein Lösungsvorschlag. Jemand anderes schlug eine Lösung mit sed vor, die in zwei Schritten arbeitet. Erst wird die Datei mit den Zuordnungen verarbeitet (das was ich oben in _ _DATA_ _ gestopft habe) und eine weitere sed-Datei erzeugt:
Code: (dl )
uidf2920 -- Schulz  wird zu s/uidf2920/Schulz/

Diese wird dann über die Logdatei laufen lassen und erzeugt das gewünschte Ergebniss.

Es gab noch einige andere interessante Lössungsvorschläge, aber zurück zu Perl und sed. Ich fand die Idee ganz interessant und dachte mir man könnte das auch in Perl mit einem Array voller anonymer Funktionen machen, sozusagen der Lambda-Weg zur Lösung. Das die Lösung mit der LookUpTable deutlich effizienter sein dürfte ist mir bewusst, aber mir ging es eher um die Umsetzung der Idee:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/perl
#
# lambda-style!
#


use strict;
use warnings;
use Data::Dumper;

my @substitutes;
for (<DATA>) {
chomp;
my ($k, $v) = split(/ -- /);
push @substitutes, sub {s/^$k/$v/;};
}

while(<>) {
for my $repl (@substitutes) { $_ =~ $repl }
print;
}

_ _DATA_ _
uidf2920 -- Bla BlaBla
uid60124 -- Maier
uidg1626 -- Muster
uidg1067 -- Mueller

Leider funktioniert mein Skript nicht wie es sollte - es führt keine Ersetzungen durch. Irgendwo muss ich etwas elementares übersehen haben, vieleicht fällt euch ja was auf?!

EDIT: Das leidige _ _DATA_ _ -Problem.\n\n

<!--EDIT|Ronnie|1110439628-->
pKai
 2005-03-10 09:56
#52491 #52491
User since
2005-02-18
357 Artikel
BenutzerIn
[default_avatar]
Sind die Variablen in den anonymen subs nicht lexikalisch ge-scoped? (Also in dem Fall garnicht belegt zum Aufrufzeitpunkt.)
Edit: Davon abgesehen, dass mir der Effekt von "...=~ $var_die_eine_sub_ref_liefert" nicht so klar ist.\n\n

<!--EDIT|pKai|1110441636-->
I sense a soul in search of answers.
pq
 2005-03-10 10:30
#52492 #52492
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
for my $repl (@substitutes) { $repl->() }
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Ronnie
 2005-03-10 10:41
#52493 #52493
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
@pq: Danke, ich wusste das es was simples sein muss, aber manchmal sieht man den Wald wegen der Bäume nicht. Ein Ampersand tut es auch.
Code: (dl )
for my $repl (@substitutes) { &$repl }

Gruß,
Ronnie
Ronnie
 2005-03-10 10:42
#52494 #52494
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
[quote=pKai,10.03.2005, 08:56]Edit: Davon abgesehen, dass mir der Effekt von "...=~ $var_die_eine_sub_ref_liefert" nicht so klar ist.[/quote]
Das Problem war, das ich vergaß zu dereferenzieren.
pKai
 2005-03-10 10:50
#52495 #52495
User since
2005-02-18
357 Artikel
BenutzerIn
[default_avatar]
Damit funktioniert es bei mir aber immer noch nicht.
Wg. der zur Aufrufzeitpunkt nicht definierten $k und $v schmeisst er bei mir nur "Use of uninitialized value in substitution (s///) at..."
Wenn ich es allerdings folgerdermaßen ändere:
Code (perl): (dl )
 push @substitutes, eval "sub {s/^$k/$v/;}";

Dann funktioniert es.
I sense a soul in search of answers.
pq
 2005-03-10 11:01
#52496 #52496
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
[quote=pKai,10.03.2005, 09:50]Damit funktioniert es bei mir aber immer noch nicht.
Wg. der zur Aufrufzeitpunkt nicht definierten $k und $v schmeisst er bei mir nur "Use of uninitialized value in substitution (s///) at..."[/quote]
dann machst du irgendwas falsch.
mit meiner geänderten zeile läuft das programm prima.
$k und $v *sind* definiert. lies dir mal perldoc perlsub bezüglich closures durch.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
pq
 2005-03-10 11:04
#52497 #52497
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
[quote=Ronnie,10.03.2005, 09:41]@pq: Danke, ich wusste das es was simples sein muss, aber manchmal sieht man den Wald wegen der Bäume nicht. Ein Ampersand tut es auch.[/quote]
wieso sind viele eigentlich fans von &$sub und &sub? was spricht denn gegen $sub->() und sub();?
der aufruf mit ampersand ist etwas, was ich immer vermeide, denn
da wird das aktuelle @_ als parameter übergeben.
$sub->() finde ich außerdem viel lesbarer, aber das ist wohl geschmackssache.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
kabel
 2005-03-10 11:31
#52498 #52498
User since
2003-08-04
704 Artikel
BenutzerIn
[default_avatar]
spassiger wirds wenn du alles in eine sub packst:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
my $substitute= sub { $_; };
for (<DATA>) {
        chomp;
        my ($k, $v) = split(/ -- /);
        print "adding correction for [$k]\n";
        $substitute= sub { my $r= shift; sub { s/^$k/$v/ or $r->() } }->( $substitute );
}

while(<>) {
        chomp;
        $substitute->();
        print $_, $/;
}
-- stefan
pKai
 2005-03-10 11:35
#52499 #52499
User since
2005-02-18
357 Artikel
BenutzerIn
[default_avatar]
[quote=pq,10.Mar..2005, 10:01]dann machst du irgendwas falsch.
mit meiner geänderten zeile läuft das programm prima.
$k und $v *sind* definiert.[/quote]
Ja, hast Recht.
Zusätzliches Newline am Ende von DATA führte bei mir zu einer zusätzlichen sub, wo dann tatsächlich die Variablen nicht initialisiert waren.
Zwischen den vielen warnings war mir dann nicht aufgefallen, dass er tatsächlich ersetzt.
I sense a soul in search of answers.
<< |< 1 2 >| >> 14 Einträge, 2 Seiten



View all threads created 2005-03-10 09:25.