Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]7895[/thread]

Kommaseparierte Listen bereichsweise ausgeben.

Leser: 1


<< |< 1 2 3 >| >> 29 Einträge, 3 Seiten
Gast Gast
 2006-04-14 16:54
#64953 #64953
Hallo zusammen :)

könnte mir jemand helfen, wie ich folgendes Problem mit Perl lösen kann? Gegeben ist eine kommaseparierte Liste. Z.B:
Quote
a=3,b=4,c=17,d=19
a=5,b=7,c=62,d=33
a=16,b=9,c=77,d=49
a=98,b=10,c=234,d=213
a=130,b=27,c=567,d=333
a=234,b=56,c=1024,d=789
a=444,b=231,c=1079,d=987


Wie man sieht, hat jede Zeile immer die gleiche Glieder vor dem Gleichheitszeichen, die immer zufälig, aber in aufsteigender Rheienfolge zum Glied in der Vorzeile aufgeführt sind. Die Aufgabe ist, dass man über Komandozeilenparameter ein Glied, ein Startwert und ein Stopwert angibt und das Perlprogram listet die Zeilen in der die Glieder grösser-gleich als Startwert und kleiner-gleich Stopwert sind.

also:

'./intervall.pl b 9 27' sucht die Liste nach "b=" durch und gibt alle Zeilen, in den b grösser-gleich 9 und kleiner-gleich 27 ist. Hier wäre es:

Quote
a=16,b=9,c=77,d=49
a=98,b=10,c=234,d=213
a=130,b=27,c=567,d=33


Kann mir jemand helfen?

Danke!
Tobias
Dubu
 2006-04-14 17:18
#64954 #64954
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Das klingt so nach Hausaufgabe ...

Woran hapert es denn? Was hast du schon probiert? Wo ist der Code?
Ronnie
 2006-04-14 17:30
#64955 #64955
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
<- snip ->
Hausaufgabe?!\n\n

<!--EDIT|Ronnie|1145021516-->
toby
 2006-04-15 01:58
#64956 #64956
User since
2006-04-14
66 Artikel
BenutzerIn
[default_avatar]
Hallo! :)

Quote
Das klingt so nach Hausaufgabe ...


Ja, ich gib zu, es war zu offensichtilich ;-)

Quote
Was hast du schon probiert? Wo ist der Code?


Nun, ich bekomme einzelne Zeilen der Liste, allerdings habe ich keine Idee, wie ich dann diese Zeile auf die Bedingung überprüfe, die per Kommandozeilenparameter gegeben wurden, ob diese Zeile ausgegeben werden darf, oder nicht.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/perl

use strict;
use warnings;

my $x=0;
my @shift;
my @liste = `cat list.txt`; # wir sind auf linux

printf "Bedingungen: @ARGV \n";

while (@liste){
@shift=shift(@liste);
print "Aktuelle Zeile ist: ", @shift;
}


Könnt mir einen kleinen Tip geben?

Danke! :)
Tobias
Taulmarill
 2006-04-15 02:06
#64957 #64957
User since
2004-02-19
1750 Artikel
BenutzerIn

user image
ich würde mir mit einem regulären ausdruck die passende zahl aus der zeile holen. hast du schon mal mit regulären ausdrücken gearbeitet?
eine andere möglichkeit währe, die zeile nach kommata und gleichheitszeichen zu splitten. wenn du das machen willst, würde ich mir mal überlegen, ob man so was nicht an einen hash übergeben könnte ...
$_=unpack"B*",~pack"H*",$_ and y&1|0& |#&&print"$_\n"for@.=qw BFA2F7C39139F45F78
0A28104594444504400 0A2F107D54447DE7800 0A2110453444450500 73CF1045138445F4800 0
F3EF2044E3D17DE 8A08A0451412411 F3CF207DF41C79E 820A20451412414 83E93C4513D17D2B
Ronnie
 2006-04-15 02:07
#64958 #64958
User since
2003-08-14
2022 Artikel
BenutzerIn
[default_avatar]
an die Kommandozeilenparameter kommst du über das Array @ARGV:
Code: (dl )
my ($key, $min, $max) = @ARGV;

ausgeben willst du eine Zeile wenn in der Zeile der Suchschlüssel gefunden wird und dessen numerischer Wert (nach dem '=') größer oder gleich dem Minimalwert ist und kleiner oder gleich dem Maximalwert:
Code: (dl )
m/$key=(\d+)/ && $1 >= $min && $1 <= $max

Das einlesen der Eingangsdaten sollte allerdings nicht so erfolgen:
Quote
Code: (dl )
my @liste = `cat list.txt`; # wir sind auf linux

Schau dir mal http://perldoc.perl.org/functions/open.html an.
renee
 2006-04-15 02:16
#64959 #64959
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Code: (dl )
1
2
3
4
5
[...]
while (@liste){
@shift=shift(@liste);
print "Aktuelle Zeile ist: ", @shift;
}[...]


Wenn Du shiftest, wird nur ein Element zurückgegeben. Es ist daher etwas unnötig, mit einem Array (@shift) zu arbeiten...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
toby
 2006-04-15 03:59
#64960 #64960
User since
2006-04-14
66 Artikel
BenutzerIn
[default_avatar]
Hallo zusammen! :)

vielen Dank für Eure Tips! Nun sieht meine (unsere ;-) ) Lösung der Hausaufgabe so aus:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/perl

use strict;
use warnings;

my ($key, $min, $max) = @ARGV;

open LISTE, "list.txt";
my @liste=<LISTE>;

while(@liste){
$_=shift(@liste);
if (m/$key=(\d+)/ && $1 >= $min && $1 <= $max){
print;
}
}

close(LISTE);


Geht das so, oder habe ich da noch grobe Patzer, wie vorhin mit dem skalar und dem Filehandling?

Um ehrlich zu sein, habe ich den reg exp nicht verstanden, daher werde ich gleich noch lesen, was das gemau macht.

Danke auch für den Fingerzeig zum Filehandling! Dazu habe ich aber doch noch eine Frage:

Warum kann ich aber nicht direkt mit while() auf das Handle "LISTE" zugreifen?

Code: (dl )
1
2
3
4
5
6
7
8
open LISTE, "list.txt";

while(<LISTE>){
$_=shift(@_);
if (m/$key=(\d+)/ && $1 >= $min && $1 <= $max){
print;
}
}


Dies produziert mir: "Use of uninitialized value in pattern match (m//) at ./test.pl line 13, <LISTE> line 1". Muss ich immer unbedingt den "Umweg" über "@liste" machen?

Danke und lieben Gruß!
Tobias\n\n

<!--EDIT|toby|1145059293-->
Dubu
 2006-04-15 04:44
#64961 #64961
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
Wenn du while (<LISTE>) schreibst, muss natürlich das $_ = shift(@irgendwas) weg. Das while (<LISTE>) füllt schon automatisch Zeile für Zeile in $_.



Edit: Typo.\n\n

<!--EDIT|Dubu|1145061894-->
murphy
 2006-04-15 04:49
#64962 #64962
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Prinzipiell sieht das Programm ganz gut aus. Aber ein paar Anmerkungen hätte ich da noch:

- Die while-Schleife über das Handle funktioniert nicht, weil der Befehl
Code: (dl )
$_=shift(@_);
sinnlos ist und auf das in diesem Kontext leere @_ zugreift. Die while-Schleife initialisiert dir $_ bereits automatisch bei jedem Durchlauf mit der eingelesenen Zeile aus FILE.

- Wenn du die Lösung wählst, bei der die Liste gleich komplett eingelesen wird, dann kannst du die Eingabedatei auch nach der Zuweisung wieder schließen. Es ist generell eine sinnvolle Sache, den Geltungsbereich aller Datenobjekte möglichst klein zu halten, das minimiert Fehlerquellen.

- Du solltest die Datei besser mit Fehlerüberprüfung öffnen, also zum Beispiel so:
Code: (dl )
open LISTE, "list.txt" or die "Fehler beim Öffnen der Eingabedatei: $!\n";
Allerdings wäre es meiner Meinung nach noch schöner, das Einlesen so zu schreiben:
Code: (dl )
1
2
3
4
5
my @lines;
{
 open my $in, '<', 'list.txt' or die "Fehler beim Öffnen der Eingabedatei: $!\n";
 @lines = <$in>;
}

Das verschmutzt nicht den globalen Namensraum mit einem Filehandle LISTE, schließt die Datei automatisch am Ende des geschweift geklammerten Blockes und es ist -- im Hinblick darauf, dass man den Dateinamen vielleicht mal aus einer Variablen nehmen will -- sicherer als deine Variante durch die explizite Angabe des Dateizugriffsmodus '<' (nur lesen) in einem eigenen Parameter.

- Der reguläre Ausdruck, den du verwendest um die Eingabezeilen auszuwerten, funktioniert, denke ich, nicht immer. Zum Beispiel kriegst du da Probleme, wenn eine Variable in deinen Eingabezeilen 'foo' heißt und jemand an der Kommandozeile angibt, dass nach 'o' gesucht werden soll. Dann erwischt dein regulärer Ausdruck immer auch 'foo'... Lies dir am besten mal perlrequick und/oder perlretut durch um einen Überblick über reguläre Ausdrücke zu bekommen ;-)
When C++ is your hammer, every problem looks like your thumb.
<< |< 1 2 3 >| >> 29 Einträge, 3 Seiten



View all threads created 2006-04-14 16:54.