User since
2008-07-23
11
Artikel
BenutzerIn
Hallo Perl-Gemeinde,
da ich absoluter Perl-Newbie bin (hab mich gerade abgemeldet, also bin ich der "Neue" ;-) ),
ich durch die SuFu nix gefunden hab, stelle ich hier mal meine Frage
(Problemstellung) vor - vlt. kann ja einer von euch mir weiterhelfen.
Im Voraus schon mal besten, vielen Dank für eure Zeit und eure Lsgs.vorschläge.
Euer
Ens
Also...es existiert ein Textfile, welches ich so einlese:
# open file
open(INFILE, "test.txt") or die "Kann Input-Datei nicht öffnen: $!";
# read data and store it into an array
my @lines = <INFILE>;
# close file
close INFILE;
Dieses Array filtere ich nach speziellen Ausdrücken:
my @req = grep { /BAPI_RSLT_REQ_ISOMSG/ } @lines; #find all requests
my @resp = grep { /BAPI_RSLT_RESP_ISOMSG/ } @lines; #find all responses
Nun habe ich 2 Arrays, welche eine identische Anzahl von Elementen haben.
(das ist sicher!)
Frage1: wie kann ich nun die beiden Arrays ala
newArray[0] = req[0] . '***' . resp[0]
"verbinden", ohne! eine Schleife benutzen zu müssen (wenns denn überhaupt geht)?
Obige Zeile gilt ja nur für ein Element und mit 'for each' kenne ich den Index nicht, über welchen ich auf die Arrays zugreifen müsste.
=> nur eine einfache for-schleife verwendbar?
Alternativen:
1. Mit Hashes geht nicht, da doppelte Einträge vorkommen.
2. Push hat m.W. nur einen Parameter zum Anhängen
- ich weiß nicht wie das funktionieren könnte?
User since
2006-01-27
3890
Artikel
HausmeisterIn
Warum wilst Du keine Schleife verwenden?
Wenn Du sicher bist, dass beide Arrays die gleiche Anzahl haben, schreit es danach eine Schleife einzusetzen:
if ( $#array1 == $#array2 ) {
for my $idx ( 0 .. $#array1 ) {
print $array1[$idx] . '***' . $array2[$idx] . $/;
}
}
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
User since
2007-05-11
923
Artikel
HausmeisterIn
Also in Perl 5 kommst du um eine Schleife nicht drum herum, auch wenn du sie tarnen kannst:
my @newArray = map { $req[$_] . '***' . $resp[$_] } 0 ... $#resp;
Auch hier wieder die Annahme, dass beide Arrays gleich lang sind.
In Perl 6 kannst du das mit verschachtelten Hyper-Operatoren erschlagen:
my @newArray = (@req >>~>>"***"") >>~<< @resp;
(ungetested, weil noch nicht implementiert ;-)
User since
2008-07-23
11
Artikel
BenutzerIn
Hallo,
vielen Dank für die schnellen Antworten.
Also die "getarnte Schleife" ist genau das, was ich gesucht habe ;-)
Map - soweit hatte ich das Buch noch nicht durch.
Klar ist, dass intern eine Schleife abgearbeitet wird,
und das man das Problem mittels einer for Schleife lösen kann.
Wenn ich jedoch ein Schleife nutzen muss, dann kann ich die Datei
auch mittels Schleife einlesen und verarbeiten
(dann könnte ich mir grep, map usw. alles sparen).
OK, aber nun hätte ich eine weitere (Newbie-) Frage:
mittels
my @req = grep { /BAPI_RSLT_REQ_ISOMSG/ } @lines; #find all requests
habe ich ein Array von Zeilen, welche das Suchmuster enthalten
(BAPI_RSLT_REQ_ISOMSG).
Frage:
Kann ich das Suchmuster als "dynamischen Parameter" übergeben?
Bsp. ein Array von Suchmustern
@pattern = ("suchmuster_1", "suchmuster_2", ...);
und dann so etwas (in der Art)
my @req = grep { /@pattern/ } @lines; #find all requests
D.h. die Zeilen sollen gemäß de Pattern gefiltert werden.
Ist sowas möglich?
und wenn ja, wie?
Vlt. könnt ihr mir wieder helfen.
Danke
Ens
User since
2006-01-27
3890
Artikel
HausmeisterIn
So kommt die eine Anforderung zur nächsten... und schnell ist man an dem Punkt angekommen, wo es keinen Sinn oder Mehrwert mehr hat, das ganze ohne Schleife realisieren zu wollen.
Ich würde die Datei zeilenweise einlesen und dabei dann das Matching machen und die Ergebnisausgabe machen.
Sind Deine Suchmuster statischer Text oder Regex?
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
User since
2008-07-23
11
Artikel
BenutzerIn
Yep Linuxer,
da geb ich dir voll Recht mit dem Sinn / Mehrwert.
Es ist nur so, dass eine Schleife ewig braucht und nur einen Teil zu filtern braucht, während die Verarbeitung der gefundenen Zeilen relativ aufwendig ist.
Und wenn man solche Funktionen wie grep o.ä. nutzen kann....
(lt. Buch(1): "..die Kurzform ist ...effizienter und bequemer." )
Aber vlt. ist es besser die gesamte Problemstellung aufzuzeigen:
kleiner Auszug einer Textdatei:
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 00
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 00 00 00 04 03
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 54
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 54 00 46
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 55
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 55 00 46
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 50
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 50 07 1D 00
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 51
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 51 08 12 00
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 53
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 53 08 0B 00
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 11
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 11 30 33 37 35 34 35 33 34 33 32
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 21
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 21 32 31 32 34 34 32 32 33 33 32
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 31
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 7F 22 31
Es geht nun darum, immer Paare von Anfrage und Antwort zu extrahieren.
Die Datei kann bis zu 2GB gross sein!
Die Datei enthält auch noch andere Zeilen, welche (erstmal) nicht von Bedeutung sind, aber von ihrer Anzahl wesentlich grösser sind, als die 00/20er Paare.
Die Paare korrelieren (hoffe das ist der richtige Ausdruck ;-) ), d.h.
sind immer paarweise zu betrachten: Anfrage-Antwort.
Die Anfrage ist immer an der selben Stelle zu suchen/finden.
(es interessieren nur die Zahlenwerte nach [Tester])
Die Antworten(Zahlenwerte) beginnen immer nach ']', wobei diese Position veränderlich ist.
Ziel ist es nun, möglichst schnell !, alle Paare zu finden, die Zahlenwerte zu extrahieren(Hex) und paarweise wieder zu verknüpfen, damit
eine Anzeige in MS Ex..l erfolgen kann.
(Ja wir verwenden MS ..;-) )
In VBA würde ich sowas mit $Instr(..) machen - Perl substr(..)
Das ist schon klar, aber wie gesagt eine Schleife ...ungern.
Hoffe, das Problem ist nun klar...und vielen Dank, dass ihr euch für mich Zeit nehmt.
Gruss
Ens
(1): Einführung in Perl, O'Reilly, R. L. Schwartz, T. Phoenix, B. d Foy
User since
2006-01-27
3890
Artikel
HausmeisterIn
und es interessieren nur jene Zeilen, die mit '00 BAPI' oder '20 BAPI' beginnen?
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
User since
2006-01-27
3890
Artikel
HausmeisterIn
Hi,
ohne zu wissen, wie die Schleife implementiert ist, kann man sie nur schwer beurteilen...
Es hängt immer davon ab, wie simpel/komplex die gewünschten Aktionen sind, die mit der Schleife oder dem grep durchgeführt werden sollen.
Wie wärs hiermit?
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use strict;
use warnings;
my @result = ();
while ( my $line = <DATA> ) {
chomp $line;
if ( index( $line, '00 BAPI', 0 ) == 0 ) {
push @result, substr( $line, rindex( $line, ']')+2 ) . '***';
}
elsif ( index( $line, '20 BAPI', 0 ) == 0 ) {
$result[-1] .= substr( $line, rindex( $line, ']')+2 );
}
}
{
local $" = local $\ = $/ ;
print "@result";
}
__END__
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 00
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 00 00 00 04 03
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 54
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 54 00 46
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 55
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 55 00 46
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 50
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 50 07 1D 00
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 51
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 51 08 12 00
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 53
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 53 08 0B 00
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 11
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 11 30 33 37 35 34 35 33 34 33 32
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 21
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 62 F1 21 32 31 32 34 34 32 32 33 33 32
00 BAPI_RSLT_REQ_ISOMSG [TESTER] 22 F1 31
20 BAPI_RSLT_RESP_ISOMSG [HSCAN_UDS_500;RDU_212.RDU_212_000004_not_released] 7F 22 31
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
User since
2008-07-23
11
Artikel
BenutzerIn
Hi,
also danke nochmals für die Antworten und eure investierte Zeit.
Denke, ich werde nicht herumkommen eine Schleife zu benutzen,
um die Datei zeilenweise zu verarbeiten.
Habe deinen Code auch ausprobiert Linuxer - hat nach einer kleinen Modifikation geklappt (Dateihandle). Danke.
Allerdings hat die Verarbeitung bei einer Originaldatei ca. 10s gedauert.
Naja..ein Übel muss man wohl sterben ;-)
Denke, der Thread kann geschlossen werden.
Werde aber noch einen "Neuen" aufmachen..hab da noch ne Frage ;-)
Also
vielen Dank nochmals
Ens
User since
2003-08-21
2614
Artikel
ModeratorIn
mesh in
List::MoreUtils?
Edit: Hm, vielleicht doch nicht, der Teil mit den Sternchen wird schwer.