Font
[thread]7430[/thread]

Datei mit Tabstops umstrukturieren



<< |< 1 2 >| >> 12 entries, 2 pages
roeschu
 2005-11-04 11:04
#59697 #59697
User since
2005-11-04
6 articles
BenutzerIn
[default_avatar]
Hallo

Ich möchte die Logs einer Telefonanlage umstrukturieren damit ich gewisse Auswertungen machen kann. Leider ist die Struktur des Logfiles ziemlich mmmh scheisse...mir fehlt ein sinnvoller Ansatz/Beginn.

Ueberlegt habe ich mir, müsste ich mal in einem ersten Schritt bewerkstelligen Zeile für Zeile in ein Array einzulesen und dann Zeile für Zeile in ein andere Datei welche ich kommaseparaiert strukturiere einzulesen. In einer CSV strukturierten Datei könnte ich dann bequemer auswerten (z.B wie im Thread "Auslesen aus .txt bis Trennzeichen, wie?") . Bloss anhand von was separiere ich die Werte im Array? Anhand der Tabstops im Originalfile? Wie man Tabstops "liest" ist auch beschrieben im anderen Thread nur in meinem Fall kommt ja dazu das Zeile für Zeile grundsätzlich anders aussieht..

Hat jemand einen sinnvollen Ansatz und Tips für diese Aufgabe? Ich bin auch nicht abgeneigt cpan module zu benützen.

Ein Beispiel für eine Logdatei findet der interessierte User hier: http://makeashorterlink.com/?F2C052A1C


grüsse\n\n

<!--EDIT|roeschu|1131095198-->
Dubu
 2005-11-04 11:20
#59698 #59698
User since
2003-08-04
2145 articles
ModeratorIn + EditorIn

user image
Es wäre interessant zu wissen, welche Informationen dich denn überhaupt interessieren in der Datei und wie diese dann abgelegt werden sollen.

Prinzipiell ist die Datei schon gut strukturiert. Die Zeilen mit dem Start eines Vorgangs (jedenfalls nehme ich an, dass es das ist) sind auch gut zu erkennen an den Strichen vorne. Mit "Tabstopps" meinst du wahrscheinlich die Aufteilung in (zwei) Spalten innerhalb der Zeilen, denn Tabs habe ich keine gefunden im Text.
Dubu
 2005-11-04 11:24
#59699 #59699
User since
2003-08-04
2145 articles
ModeratorIn + EditorIn

user image
Ach ja: Spaltenorientierte Daten kann man nicht nur mit substr() sondern auch sehr elegant mit unpack() auseinander pflücken. Siehe Wiki:perlpacktut.
roeschu
 2005-11-04 11:40
#59700 #59700
User since
2005-11-04
6 articles
BenutzerIn
[default_avatar]
[quote=Dubu,04.Nov..2005, 10:20]Es wäre interessant zu wissen, welche Informationen dich denn überhaupt interessieren in der Datei und wie diese dann abgelegt werden sollen.[/quote]
Grundsätzlich sind es diese Abschnitte die ich benötige:

--------   10/27/05   10:01:52   LINE = 0241   STN = 2152    
          CALLING NUMBER   0435487868
          NAME             UNKNOWN        
          UNKNOWN
          DNIS NUMBER      2121
          BC = SPEECH
00:00:00   INCOMING CALL    RINGING 0:04
          LINE = 0093
....

Am Schluss muss ich einfach auswerten welche interne Nummer  (hier 2152) welche externe Nummer wählt (hier 0435487868 ) und wieviele externe Calls ein interner Client gemacht hat. Ich glaube das ist auch nicht so wahnsinnig schwer...vorrausgesetzt ich bringe es fertig das Logfile in ein sinnvolle CSV Struktur umzuwandeln.


Meine Ueberlegung war nun Zeile für Zeile in ein CSV File einzulesen. Also die erste Zeile

--------   10/27/05   10:01:52   LINE = 0241   STN = 2152

würde dann so aussehen

--------;10/27/05;10:01:52;LINE = 0241;STN = 2152    


Als Tabstopp bezeichne ich die Zwischenräume (siehe "Hausdach"):


--------   10/27/05   10:01:52   LINE = 0241   STN = 2152
           ^             ^             ^                 ^
roeschu
 2005-11-04 11:42
#59701 #59701
User since
2005-11-04
6 articles
BenutzerIn
[default_avatar]
[quote=Dubu,04.Nov..2005, 10:24]Ach ja: Spaltenorientierte Daten kann man nicht nur mit substr() sondern auch sehr elegant mit unpack() auseinander pflücken. Siehe Wiki:perlpacktut.[/quote]
perlpacktut....sieht eigentlich so aus als ob es das wäre...muss ich mal ausprobieren..
Dubu
 2005-11-04 12:33
#59702 #59702
User since
2003-08-04
2145 articles
ModeratorIn + EditorIn

user image
Sorry, aber der Abschnitt, den du gezeigt hast, sieht für mich eher nach einem eingehenden Anruf aus!?

IMHO ist das ein ausgehender Anruf:
Code: (dl )
1
2
3
4
5
6
--------   10/27/05   10:03:09   LINE = 0119   STN = 1101    
BC = SPEECH
00:00:00 OUTGOING CALL
DIGITS DIALED 0546878***
CALL CHARGE = 0.10 FR.
00:01:26 CALL RELEASED



Noch eine Anmerkung: Unter der Annahme, dass das schweizerische Datenschutzgesetz nicht grundsätzlich anders ist als das deutsche, und das - so wie es aussieht - die Datei vollständige Telefonnummern enthält, kannst du dich ganz schön in die Nesseln setzen mit so einer Auswertung. (Abgesehen von der Veröffentlichung der Datei hier mit den Daten ...)
Telefonnummern sind (sofern man sie nicht mit mehreren anderen teilt) personenbezogene Daten und somit datenschutzrechtlich sehr sensibel!
roeschu
 2005-11-04 12:39
#59703 #59703
User since
2005-11-04
6 articles
BenutzerIn
[default_avatar]
[quote=Dubu,04.Nov..2005, 11:33]Sorry, aber der Abschnitt, den du gezeigt hast, sieht für mich eher nach einem eingehenden Anruf aus!?

IMHO ist das ein ausgehender Anruf:
Code: (dl )
1
2
3
4
5
6
--------   10/27/05   10:03:09   LINE = 0119   STN = 1101    
          BC = SPEECH
00:00:00   OUTGOING CALL
          DIGITS DIALED    0546878***
          CALL CHARGE = 0.10 FR.
00:01:26   CALL RELEASED



Noch eine Anmerkung: Unter der Annahme, dass das schweizerische Datenschutzgesetz nicht grundsätzlich anders ist als das deutsche, und das - so wie es aussieht - die Datei vollständige Telefonnummern enthält, kannst du dich ganz schön in die Nesseln setzen mit so einer Auswertung. (Abgesehen von der Veröffentlichung der Datei hier mit den Daten ...)
Telefonnummern sind (sofern man sie nicht mit mehreren anderen teilt) personenbezogene Daten und somit datenschutzrechtlich sehr sensibel![/quote]
Ja ist richtig ist ein eingehender Anruf. Wobei ich ergänzen muss das ich beides Analysiere...sowohl incoming wie outgoing


p.s die telnr. im log entsprechen nicht den tatsächlichen...hab zufallszahlen reingetan..
Dubu
 2005-11-04 13:10
#59704 #59704
User since
2003-08-04
2145 articles
ModeratorIn + EditorIn

user image
Ach so, incoming und outgoing. Sag das doch gleich ... ;)

Hier ist mal ein Ansatz, der nur mit Regexen arbeitet, ohne unpack(). Der einzige Trick hier ist, dass ich den INPUT_RECORD_SEPARATOR umgesetzt habe, um die Datensätze zu trennen:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#!/usr/bin/perl
use strict;
use warnings;

# Datensatztrenner beim Einlesen
$/ = "\n\n--------";

while (<>) {
   # lokale Variablen
   my ($date, $time, $localphone, $remotephone, $duration) = (0,0,0,0,0);

   # abgehender Anruf
   if (/OUTGOING CALL/) {
       # Datum, Uhrzeit und lokale Nummer merken
       if (/\A\s+(\d\d\/\d\d\/\d\d)\s+(\d\d:\d\d:\d\d)\s+LINE\s*=\s*\d+\s+STN\s*=\s*(\d+)/) {
           $date = $1;
           $time = $2;
           $localphone = $3;
       } else {
           warn "OUT: Kein Datum, Uhrzeit oder lokale Nummer in Datensatz:\n$_\n";
       }

       # Angerufene Nummer merken
       if (/\n\s+DIGITS DIALED\s+(\d+)/) {
           $remotephone = $1;
       } else {
           warn "OUT: Kein angerufene Nummer in Datensatz:\n$_\n";
       }

       # Anrufdauer merken
       if (/\n(\d\d:\d\d:\d\d)\s+CALL RELEASED/) {
           $duration = $1;
       } else {
           warn "OUT: Keine Anrufdauer in Datensatz:\n$_\n";
       }

       # Alles in einer Zeile ausgeben
       print "OUT,$date,$time,$localphone,$remotephone,$duration\n";

   # eingehender Anruf
   } elsif (/INCOMING CALL/) {
       my $whatsnext = '---';  # noch eine lokale Variable

       # Datum, Uhrzeit und lokale Nummer merken
       if (/\A\s+(\d\d\/\d\d\/\d\d)\s+(\d\d:\d\d:\d\d)\s+LINE\s*=\s*\d+\s+STN\s*=\s*(\d+)/) {
           $date = $1;
           $time = $2;
           $localphone = $3;
       } else {
           warn "IN: Kein Datum, Uhrzeit oder lokale Nummer in Datensatz:\n$_\n";
       }

       # Anrufende Nummer merken
       if (/\n\s+CALLING NUMBER\s+(\d+)/) {
           $remotephone = $1;
       } else {
           warn "IN: Kein anrufende Nummer in Datensatz:\n$_\n";
       }

       # Anrufdauer und Ergebnis merken
       # TODO: statt "HANG UP" sollte das stehen, was im Log auftaucht,
       # wenn der Anrufer auflegt, ohne angenommen worden zu sein.
       if (/\n(\d\d:\d\d:\d\d)\s+(CALL RELEASED|TRANSFERRED|HANG UP)/) {
           $duration = $1;
           $whatsnext = $2;
       } else {
           warn "IN: Keine Anrufdauer in Datensatz:\n$_\n";
       }

       # Alles in einer Zeile ausgeben
       print "IN,$date,$time,$localphone,$remotephone,$duration,$whatsnext\n";

   } # alles andere ignorieren
}


Mit deinen Daten sieht das Ergebnis so aus:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ ./phonelog2csv.pl sonnemondesonnemondsonnemond > phone.csv
IN: Kein anrufende Nummer in Datensatz:
  10/27/05   10:07:31   LINE = 0241   STN = 2152
          BC = SPEECH
00:00:00   INCOMING CALL    RINGING 0:04
          LINE = 0092
00:00:36   CALL RELEASED

--------
$ cat phone.csv
IN,10/27/05,10:01:52,2152,0435487868,00:00:19,TRANSFERRED
OUT,10/27/05,10:03:09,1101,0546878798,00:01:26
OUT,10/27/05,10:05:27,2116,0546878798,00:00:59
OUT,10/27/05,10:05:29,1101,0318786877,00:01:50
OUT,10/27/05,09:59:01,1135,0318786877,00:09:05
IN,10/27/05,10:07:31,2152,0,00:00:36,CALL RELEASED
OUT,10/27/05,10:06:30,2116,054787878,00:02:22
IN,10/27/05,10:09:03,2105,079878787,00:00:48,CALL RELEASED
IN,10/27/05,10:02:04,1146,0313133131,00:07:47,CALL RELEASED
$

Die Warnmeldung erscheint, wie man sieht, nur auf STDERR, sodass sie bei einer Umleitung der Ausgabe wie oben nicht mit umgeleitet wird.

Das Skript behandelt so nur eingehende und ausgehende, aber keine weitergeleiteten Anrufe. Aber vielleicht kannst du darauf aufbauen. Man koennte es auch noch etwas schoener machen, dass nicht gleiche Teile (z.B. fuer Datum/Uhrzeit/lokale Nummer) mehrfach auftauchen.
roeschu
 2005-11-04 13:20
#59705 #59705
User since
2005-11-04
6 articles
BenutzerIn
[default_avatar]
läck, gehts noch :) ...super beispiel merci. Muss das jetzt mal ein paar Stunden analysieren... Unpack() hat gut ausgehsehen, allerdings gibts dort die Schwierigkeit (bei meiner Struktur) das jede Zeile wieder andere Inhalte an anderen "bitstellen" hat.

Merci, ich guck jetzt mal dein Beispiel an und versuch auf deinem Fundament was "eigenes" zu machen..

grüsse
Dubu
 2005-11-04 13:51
#59706 #59706
User since
2003-08-04
2145 articles
ModeratorIn + EditorIn

user image
Falls die Regexen zu kryptisch wirken: perlretut ist eine gute Einführung.
<< |< 1 2 >| >> 12 entries, 2 pages



View all threads created 2005-11-04 11:04.