[PHP][REGEXP] herkennen \n\n ipv \n

Pagina: 1
Acties:
  • 101 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Scout77
  • Registratie: September 2002
  • Laatst online: 01-01 21:22
Ik heb aan mijn server een Siemens telefoon gehangen en nu wil ik daar de sms-jes van af willen halen en opslaan in een db zodat ik daar later dan meer mee kan doen. Ik gebruik het onderstaande php script om de informatie eruit te halen. Daarmee kom ik een eind maar met het opzoeken van een bericht met enters erin gaat het mis.

PHP:
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
<?php

$output = shell_exec('scmxx --get --sms --slot=all --out=- 2>&1');
echo "<pre>$output</pre>\n\n";

$regex = '|From: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $from);
print_r($from[1]);

$regex = '|Date: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $date);
print_r($date[1]);

$regex = '|SMSC number: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $smsc);
print_r($smsc[1]);

$regex = '|PDU type: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $pdu_type);
print_r($pdu_type[1]);

$regex = '|PDU flags: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $pdu_flags);
print_r($pdu_flags[1]);

$regex = '|Settings: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $settings);
print_r($settings[1]);

$regex = '|Message length: ([^\n]+)*|';
$count = preg_match_all($regex, $output, $lenght);
print_r($lenght[1]);

$regex = '|Message length:[^\n\n]*\n\n([^\n\n]+)\n\n*|';
$count = preg_match_all($regex, $output, $message);
var_dump($message);
//print_r($message[1]);
?>


Uitvoer shell_exec:
code:
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
<pre>Using "ANSI_X3.4-1968" as system character set.
Accessing device /dev/ttyS0...done
OK, a modem device is present.
Detected SIEMENS M35i
Looking for SMS of specified type...
Found incoming, read SMS in slot 1.
Found incoming, read SMS in slot 2.
Found incoming, read SMS in slot 3.
Found incoming, read SMS in slot 4.
Slot: 1
From: 712
Date: Wed Oct  4 00:03:19 2006
SMSC number: +31624000000
PDU type: SMS-DELIVER
PDU flags: MoreMessagesToSend ReplyPath
Settings: 7bit-GSM
Message length: 111

Welkom bij T-Mobile.
Je gebruikersnaam is: USERNAME
Je wachtwoord is: USERCODE
Met de groeten van T-Mobile.

Slot: 2
From: (T-Mobile NL)
Date: Wed Oct  4 00:39:58 2006
SMSC number: +31624000000
PDU type: SMS-DELIVER
PDU flags: StatusRequest MoreMessagesToSend
Settings: 7bit-GSM
Message length: 154

Welkom bij T-Mobile. T-Mobile geeft je 400 gratis SMSjes. Deze zijn aan je tegoed toegevoegd. Je kunt de gratis SMSjes gebruiken tot en met 31 maart 2007.

Slot: 3
From: (T-Mobile NL)
Date: Wed Oct  4 17:45:23 2006
SMSC number: +31624000000
PDU type: SMS-DELIVER
PDU flags: StatusRequest MoreMessagesToSend
Settings: 7bit-GSM
Message length: 99

Je internet bestelling bij TM-Speciaal is verwerkt. Binnen 2 weken ontvang je het bestelde artikel.

Slot: 4
From: (T-Mobile NL)
Date: Wed Oct  4 17:45:30 2006
SMSC number: +31624000000
PDU type: SMS-DELIVER
PDU flags: StatusRequest MoreMessagesToSend
Settings: 7bit-GSM
Message length: 74

Uw beltegoed is met EUR 10,00 opgewaardeerd. Uw beltegoed is nu EUR 15,00.

</pre>


Overige uitvoer:
code:
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
Array
(
    [0] => 712
    [1] => (T-Mobile NL)
    [2] => (T-Mobile NL)
    [3] => (T-Mobile NL)
)
Array
(
    [0] => Wed Oct  4 00:03:19 2006
    [1] => Wed Oct  4 00:39:58 2006
    [2] => Wed Oct  4 17:45:23 2006
    [3] => Wed Oct  4 17:45:30 2006
)
Array
(
    [0] => +31624000000
    [1] => +31624000000
    [2] => +31624000000
    [3] => +31624000000
)
Array
(
    [0] => SMS-DELIVER
    [1] => SMS-DELIVER
    [2] => SMS-DELIVER
    [3] => SMS-DELIVER
)
Array
(
    [0] => MoreMessagesToSend ReplyPath
    [1] => StatusRequest MoreMessagesToSend
    [2] => StatusRequest MoreMessagesToSend
    [3] => StatusRequest MoreMessagesToSend
)
Array
(
    [0] => 7bit-GSM
    [1] => 7bit-GSM
    [2] => 7bit-GSM
    [3] => 7bit-GSM
)
Array
(
    [0] => 111
    [1] => 154
    [2] => 99
    [3] => 74
)
array(2) {
  [0]=>
  array(4) {
    [0]=>
    string(42) "Message length: 111

Welkom bij T-Mobile.
"
    [1]=>
    string(177) "Message length: 154

Welkom bij T-Mobile. T-Mobile geeft je 400 gratis SMSjes. Deze zijn aan je tegoed toegevoegd. Je kunt de gratis SMSjes gebruiken tot en met 31 maart 2007.

"
    [2]=>
    string(121) "Message length: 99

Je internet bestelling bij TM-Speciaal is verwerkt. Binnen 2 weken ontvang je het bestelde artikel.

"
    [3]=>
    string(96) "Message length: 74

Uw beltegoed is met EUR 10,00 opgewaardeerd. Uw beltegoed is nu EUR 15,00.

"
  }
  [1]=>
  array(4) {
    [0]=>
    string(20) "Welkom bij T-Mobile."
    [1]=>
    string(154) "Welkom bij T-Mobile. T-Mobile geeft je 400 gratis SMSjes. Deze zijn aan je tegoed toegevoegd. Je kunt de gratis SMSjes gebruiken tot en met 31 maart 2007."
    [2]=>
    string(99) "Je internet bestelling bij TM-Speciaal is verwerkt. Binnen 2 weken ontvang je het bestelde artikel."
    [3]=>
    string(74) "Uw beltegoed is met EUR 10,00 opgewaardeerd. Uw beltegoed is nu EUR 15,00."
  }
}
Ipv het bericht :
"Welkom bij T-Mobile.
Je gebruikersnaam is: USERNAME
Je wachtwoord is: USERCODE
Met de groeten van T-Mobile."

Stopt het bij de eerste regel:
"Welkom bij T-Mobile."

Probleem is dat die \n\n dus niet wordt gebruikt maar een enkele \n. Er gaat dus nog iets mis in deze regels:
PHP:
1
2
3
$regex = '|Message length:[^\n\n]*\n\n([^\n\n]+)\n\n*|';
$count = preg_match_all($regex, $output, $message);
var_dump($message);


Iemand een idee hoe dat op te lossen? Door zoeken tot de volgende "slot:" is geen optie omdat dan de laatste niet mee komt.

Lekker belangrijk


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Een characterclass [] matched maar 1 karakter, [^\n\n] is dus hetzelfde als [^\n]

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Scout77
  • Registratie: September 2002
  • Laatst online: 01-01 21:22
PHP:
1
$regex = '|Message length:[^\n]*\n\n([^\n]+)\n\n*|';


Dit geeft idd hetzelfde resultaat, maar dan moet die toch nog steeds door gaan tot die \n\n ?

Lekker belangrijk


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:04
Het stuk met de message length gaat waarschijnlijk goed. Daarna gaat het mis.

Je eindigt met \n\n* dat is hetzelfde als \n+ (want het sterretje betekent '0 of meer' en werkt op de expressie er direct voor, alleen die tweede \n dus), oftewel één óf méér newlines (niet exact twee), vandaar dat het einde van de eerste regel al matcht.

De expressie tussen haakjes ([\n]+) matcht echter maar één regel omdat je expliciet verbiedt dat er newline characters in voorkomen. Zelfs als je je eindconditie fixt, kun je dus niet meer dan één regel matchen (en faalt de match als geheel).

Dit is echter niet alles wat misgaat, want reguliere expressies zijn standaard greedy, wat wil zeggen dat ze zo lang mogelijke matches matchen. Beter is dus zoiets: Message length:[^\n]*\n\n(.*?)\n\n. Het vraagteken in .*? maakt de expressie .* non-greedy, waardoor de kortste tekst gematch wordt, die gevolgd wordt door twee newline characters. Hierdoor lees je het hele bericht in, tot en met de lege regel.

Merk wel op dat op deze manier berichten helemaal geen lege regels mogen bevatten. Dat is voor smsjes natuurlijk ook niet zo gebruikelijk. Beter is misschien om de message length uit te lezen, en dan simpelweg een substring van die lengte als bericht te nemen.

[ Voor 16% gewijzigd door Soultaker op 04-10-2006 17:23 ]


Acties:
  • 0 Henk 'm!

  • Scout77
  • Registratie: September 2002
  • Laatst online: 01-01 21:22
Je oplossing |Message length:[^\n]*\n\n(.*?)\n\n| geeft nog niet het gewenste resultaat en slaat een oplossing met een newline gewoon over.

Met de oplossing die ik zelf had |Message length:[^\n]*\n\n([^\n]+)\n\n*| kwam ik verder. Alleen raar dat bij het eerste bericht er maar een newline wordt weergegeven en bij de 3 volgende wel een extra newline te zien is. (Ik begrijp dat die afgekapt wordt bij de eerst volgende /n die hij tegenkomt, maar hij geeft wel meer newlines ... :?).

Zelf het nodige geprobeerd maar zelfs |Message length:[^\n]*\n\n(.*)| komt niet verder dan de eerst volgende \n in de tekst. Wat ik toch raar vind aangezien ik niet aangeef dat hij moet stoppen.

Hoe krijg ik het nu voor elkaar dat die niet moeilijk doet over een \n maar wel stopt bij \n\n ... :s

Lekker belangrijk


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 00:04
Toch klopt mijn suggestie wel, maar je moet de 's' pattern modifier zetten zodat ook newlines gematcht worden. Eventueel moet je nog wel een paar newlines aan je invoer toevoegen om ook het laatste bericht te matchen, of het einde vervangen door iets als (\n\n|$).

De vragen die je verder stelt probeer ik juist in m'n vorige post te beantwoorden. Ik heb weinig zin veel (meer) werk te maken van dit topic als je mijn uitleg negeert en vervolgens maar door blijft drammen dat je het niet begrijpt. Als je niet begrijpt waarom je een match met een enkel newline character op het eind krijgt, moet je mijn vorige post beter lezen.

[ Voor 25% gewijzigd door Soultaker op 04-10-2006 19:09 ]


Acties:
  • 0 Henk 'm!

  • Scout77
  • Registratie: September 2002
  • Laatst online: 01-01 21:22
Ik heb een andere oplossing gevonden.

str_replace("\n\n", "\t", $output)
|Message length:[^\t]*\t([^\t]+)\t*|


De dubbele newline vervangen voor iets anders die dan vervolgens met een enkele char. is te vangen.

Lekker belangrijk


Acties:
  • 0 Henk 'm!

Anoniem: 14829

Lekker simpele en doeltreffende oplossing! Regular expressions are so overrated... :+

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

En wat doe je als het SMS bericht 2 lege regels bevat?
Ik denk dat het verstandiger is om die headers te gebruiken, daarin staat immers (zoals te zien in je post) hoe lang het bericht is, dan kun je simpel zoveel bytes lezen en je hebt het hele bericht :)

Acties:
  • 0 Henk 'm!

  • Scout77
  • Registratie: September 2002
  • Laatst online: 01-01 21:22
Erkens schreef op woensdag 04 oktober 2006 @ 23:27:
En wat doe je als het SMS bericht 2 lege regels bevat?
Ik denk dat het verstandiger is om die headers te gebruiken, daarin staat immers (zoals te zien in je post) hoe lang het bericht is, dan kun je simpel zoveel bytes lezen en je hebt het hele bericht :)
Je hebt wel gelijk maar ik vraag me af hoeveel mensen twee lege regels in een sms zetten. Daarbij komt dat ik zelf degene ben die smsjes naar die telefoon verstuur dus ik ken de beperkingen.

Ik heb er wel naar gekeken maar kreeg het niet voor elkaar om vanaf de "message length" header het maximum van een sms (160) in te lezen en daar vervolgens alleen de lengte van de message over te houden. Dat laatste is niet zo moeilijk natuurlijk maar het eerste wel.

[ Voor 4% gewijzigd door Scout77 op 05-10-2006 00:27 ]

Lekker belangrijk


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Scout77 schreef op donderdag 05 oktober 2006 @ 00:25:
Je hebt wel gelijk maar ik vraag me af hoeveel mensen twee lege regels in een sms zetten. Daarbij komt dat ik zelf degene ben die smsjes naar die telefoon verstuur dus ik ken de beperkingen.
Tja, dat dacht ik ook in eerste instantie toen ik een dergelijk script maakte dat dat soort dingen dan niet uitmaakte. Vroeg of laat kom je er wel achter hoor :+
Ik heb er wel naar gekeken maar kreeg het niet voor elkaar om vanaf de "message length" header het maximum van een sms (160) in te lezen en daar vervolgens alleen de lengte van de message over te houden. Dat laatste is niet zo moeilijk natuurlijk maar het eerste wel.
Je moet het ook niet met een regex oplossen denk ik maar een simpele parser schrijven.

Wat je moet doen is de binnengekomen data gaan lezen, waarbij je leest tot je aan het begin van een regel "Slot: " tegenkomt, je weet immers dat dan je SMS begint. Dan lees je alle headers uit tot de eerste lege regel. Dan zoek je in de gelezen headers hoe lang het bericht is, dat is het aantal karakters dat het berichtje lang is en die kan je dus eenvoudig uitlezen. Daarna ga je weer verder bij het begin (zoeken naar "Slot: "). Het is echt niet zo moeilijk als het lijkt, wat je moet doen is gewoon eerst snappen hoe die output in elkaar steekt, en daarna is het schrijven van de code nog maar bijzaak, althans ik neem aan dat je wel weet hoe je strings moet uitlezen ;)
Pagina: 1